cpp-toolbox  0.0.1
A toolbox library for C++
Loading...
Searching...
No Matches
kitti_odometry_dataset_impl.hpp
Go to the documentation of this file.
1#pragma once
2
5
6#include <filesystem>
7#include <algorithm>
8
9namespace toolbox::io {
10
11template<typename DataType>
13 const std::string& sequence_path)
14 : sequence_path_(sequence_path) {
15
16 namespace fs = std::filesystem;
17
18 // Validate directory structure
19 if (!validate_kitti_sequence_directory(sequence_path)) {
20 throw kitti_invalid_sequence(sequence_path);
21 }
22
23 // Extract sequence name
24 fs::path path(sequence_path);
25 sequence_name_ = path.filename().string();
26
27 // Set paths
28 velodyne_path_ = (path / "velodyne").string();
29
30 // Scan for point cloud files
31 scan_cloud_files();
32
33 if (cloud_files_.empty()) {
34 throw kitti_invalid_sequence("No point cloud files found in: " + velodyne_path_);
35 }
36
37 // Load poses
38 // Poses are typically in the parent directory structure
39 fs::path poses_dir = path.parent_path().parent_path() / "poses";
40 std::string poses_file = (poses_dir / (sequence_name_ + ".txt")).string();
41
42 if (fs::exists(poses_file)) {
43 load_poses(poses_file);
44 } else {
45 LOG_WARN_S << "No poses file found at: " << poses_file;
46 }
47
48 // Load calibration
49 load_calibration();
50
51 LOG_INFO_S << "Loaded KITTI sequence " << sequence_name_
52 << " with " << cloud_files_.size() << " frames";
53}
54
55template<typename DataType>
57 cloud_files_ = list_kitti_cloud_files(velodyne_path_);
58
59 // Verify files are properly numbered
60 for (std::size_t i = 0; i < cloud_files_.size(); ++i) {
61 int frame_idx = parse_kitti_frame_index(cloud_files_[i]);
62 if (frame_idx != static_cast<int>(i)) {
63 LOG_WARN_S << "Frame index mismatch: expected " << i
64 << " but got " << frame_idx
65 << " for file " << cloud_files_[i];
66 }
67 }
68}
69
70template<typename DataType>
71void kitti_odometry_dataset_t<DataType>::load_poses(const std::string& poses_file) {
72 if (!pose_reader_.load(poses_file)) {
73 LOG_ERROR_S << "Failed to load poses from: " << poses_file;
74 return;
75 }
76
77 // Verify pose count matches frame count
78 if (pose_reader_.size() != cloud_files_.size()) {
79 LOG_WARN_S << "Pose count (" << pose_reader_.size()
80 << ") does not match frame count (" << cloud_files_.size() << ")";
81 }
82}
83
84template<typename DataType>
85void kitti_odometry_dataset_t<DataType>::load_calibration() {
86 namespace fs = std::filesystem;
87
88 fs::path calib_file = fs::path(sequence_path_) / "calib.txt";
89
90 if (fs::exists(calib_file)) {
91 try {
92 calibration_ = read_kitti_calibration<DataType>(calib_file.string());
93 LOG_INFO_S << "Loaded calibration from: " << calib_file;
94 } catch (const std::exception& e) {
95 LOG_WARN_S << "Failed to load calibration: " << e.what();
96 }
97 }
99
100template<typename DataType>
101std::optional<kitti_odometry_frame_t<DataType>>
103
104 if (index >= cloud_files_.size()) {
105 if (error_policy_ == error_recovery_policy_t::strict) {
106 throw kitti_index_out_of_range(index, cloud_files_.size());
107 }
108 return std::nullopt;
109 }
110
111 // Check cache first
112 auto cached = get_from_cache(index);
113 if (cached) {
114 return cached;
115 }
116
117 // Load point cloud
118 auto cloud = load_cloud(cloud_files_[index]);
119 if (!cloud) {
120 if (error_policy_ == error_recovery_policy_t::strict) {
121 throw kitti_corrupted_data("Failed to load cloud at index " +
122 std::to_string(index));
123 }
124 return std::nullopt;
125 }
126
127 // Create frame
128 frame_type frame;
129 frame.cloud = std::move(cloud);
130 frame.frame_index = index;
131
132 // Get pose if available
133 if (index < pose_reader_.size()) {
134 frame.pose = pose_reader_.get_pose(index);
135 } else {
136 // Use identity if no pose available
137 frame.pose = Eigen::Matrix<DataType, 4, 4>::Identity();
138 if (error_policy_ != error_recovery_policy_t::best_effort) {
139 LOG_WARN_S << "No pose available for frame " << index;
140 }
141 }
142
143 // Set timestamp (frame index as string for now)
144 frame.timestamp = format_kitti_frame_index(index);
145
146 // Update cache before returning
147 update_cache(index, std::move(frame));
148
149 // Return from cache to avoid move issues
150 return get_from_cache(index);
151}
152
153template<typename DataType>
154std::unique_ptr<point_cloud_t<DataType>>
156 const std::string& file_path) const {
157
158 try {
159 auto cloud = read_kitti_bin<DataType>(file_path);
160
161 if (!cloud) {
162 LOG_ERROR_S << "Failed to read point cloud from: " << file_path;
163 return nullptr;
164 }
165
166 // Optionally clear intensity if not needed
167 if (!load_intensity_) {
168 cloud->intensity = 0;
169 }
170
171 return cloud;
172
173 } catch (const std::exception& e) {
174 LOG_ERROR_S << "Exception loading point cloud from " << file_path
175 << ": " << e.what();
176 return nullptr;
177 }
178}
179
180template<typename DataType>
181void kitti_odometry_dataset_t<DataType>::update_cache(
182 std::size_t index, frame_type&& frame) const {
183
184 // Remove from LRU list if already present
185 auto it = std::find(lru_list_.begin(), lru_list_.end(), index);
186 if (it != lru_list_.end()) {
187 lru_list_.erase(it);
188 }
189
190 // Add to front of LRU list
191 lru_list_.push_front(index);
192
193 // Insert/update in cache
194 cache_[index] = std::move(frame);
195
196 // Evict oldest if cache is full
197 while (cache_.size() > max_cache_size_ && !lru_list_.empty()) {
198 auto oldest = lru_list_.back();
199 cache_.erase(oldest);
200 lru_list_.pop_back();
201 }
202}
203
204template<typename DataType>
205std::optional<kitti_odometry_frame_t<DataType>>
206kitti_odometry_dataset_t<DataType>::get_from_cache(std::size_t index) const {
207
208 auto it = cache_.find(index);
209 if (it != cache_.end()) {
210 // Move to front of LRU list
211 auto lru_it = std::find(lru_list_.begin(), lru_list_.end(), index);
212 if (lru_it != lru_list_.end()) {
213 lru_list_.erase(lru_it);
214 }
215 lru_list_.push_front(index);
216
217 // Return a copy since frame contains unique_ptr
218 frame_type copy;
219 copy.cloud = std::make_unique<point_cloud_t<DataType>>(*it->second.cloud);
220 copy.pose = it->second.pose;
221 copy.frame_index = it->second.frame_index;
222 copy.timestamp = it->second.timestamp;
223 return copy;
224 }
225
226 return std::nullopt;
227}
228
229} // namespace toolbox::io
std::size_t size() const
获取数据集大小/Get the size of the dataset
Definition dataset.hpp:49
Exception thrown when data is corrupted.
Definition kitti_exceptions.hpp:42
Exception thrown when accessing out of bounds frame.
Definition kitti_exceptions.hpp:66
Exception thrown when sequence directory structure is invalid.
Definition kitti_exceptions.hpp:51
KITTI Odometry dataset loader.
Definition kitti_odometry_dataset.hpp:45
std::optional< frame_type > at_impl(std::size_t index) const
Load frame at specific index.
Definition kitti_odometry_dataset_impl.hpp:102
kitti_odometry_dataset_t(const std::string &sequence_path)
Constructor.
Definition kitti_odometry_dataset_impl.hpp:12
#define LOG_INFO_S
INFO级别流式日志的宏 / Macro for INFO level stream logging.
Definition thread_logger.hpp:1330
#define LOG_ERROR_S
ERROR级别流式日志的宏 / Macro for ERROR level stream logging.
Definition thread_logger.hpp:1332
#define LOG_WARN_S
WARN级别流式日志的宏 / Macro for WARN level stream logging.
Definition thread_logger.hpp:1331
< 用于列出目录下的文件/For listing files in a directory
Definition dataloader.hpp:15
std::string format_kitti_frame_index(std::size_t index, int digits)
Format frame index as KITTI filename (e.g., 123 -> "000123")
Definition kitti_extended_impl.hpp:405
@ strict
Throw exception on any error.
@ best_effort
Try to recover partial data.
bool validate_kitti_sequence_directory(const std::string &sequence_path)
Validate KITTI sequence directory structure.
Definition kitti_extended_impl.hpp:438
std::vector< std::string > list_kitti_cloud_files(const std::string &velodyne_path)
List all KITTI point cloud files in a directory.
Definition kitti_extended_impl.hpp:350
int parse_kitti_frame_index(const std::string &filename)
Get frame index from KITTI filename (e.g., "000123.bin" -> 123)
Definition kitti_extended_impl.hpp:392
Single frame data from KITTI odometry dataset.
Definition kitti_types.hpp:25
std::size_t frame_index
Frame index in the sequence.
Definition kitti_types.hpp:33
Eigen::Matrix< DataType, 4, 4 > pose
Global pose (4x4 transformation matrix)
Definition kitti_types.hpp:30
std::string timestamp
Optional timestamp string.
Definition kitti_types.hpp:36
std::unique_ptr< point_cloud_t< DataType > > cloud
Point cloud data.
Definition kitti_types.hpp:27