40 using Vec = BaseVector<float>;
50 std::string::size_type n = 0;
51 std::string::size_type sz = 0;
53 mat[count++] = std::stof(data.substr(n), &sz);
55 n = data.find_first_not_of(
' ', n);
62 std::regex regex(regex_string);
64 std::regex_match(data, sm, regex);
71 std::string input_cloud_format
73 :m_project_dir(
fs::path(dir))
74 ,m_input_cloud_format(input_cloud_format)
81 for (
auto scanpos_info : project_ptree.get_child(
"project.scanpositions")) {
82 if (scanpos_info.first !=
"scanposition")
continue;
86 std::string scan_name = scanpos_info.second.get<std::string>(
"name");
88 if (!scan_name.length() == 10) {
89 std::cout <<
"[RieglProject] Warning: The scanpos " << scan_name <<
" is skipped" 90 <<
" because the name is malformed." << std::endl;
95 unsigned int scan_pos_nr = std::stoul(scan_name.substr(7));
98 if (scan_pos_nr < start || (end != 0 && scan_pos_nr > end)) {
102 fs::path scan_dir =
m_project_dir / (
"SCANS/" + scan_name +
"/");
104 unsigned int scan_file_size = 0;
110 for (
auto scan_data : scanpos_info.second.get_child(
"singlescans")) {
111 if (scan_data.first !=
"scan")
continue;
113 std::string current_scan_filename = scan_data.second.get<std::string>(
"file");
116 if (current_scan_filename.find(
".mon") != std::string::npos) {
120 fs::path current_scan_file = scan_dir / (
"SINGLESCANS/" + current_scan_filename);
122 if (!fs::exists(current_scan_file) || !fs::is_regular_file(current_scan_file)) {
123 std::cout <<
"[RieglProject] Warning: The scan data file '" << current_scan_file
124 <<
"' doesn't exists or isn't a regular file and there \ 125 is gonna be skipped." << std::endl;
130 unsigned int current_scan_file_size = fs::file_size(current_scan_file);
132 if ( current_scan_file_size > scan_file_size) {
133 scanpos.scan_file = current_scan_file;
134 scan_file_size = current_scan_file_size;
140 if (scanpos.scan_file.empty()) {
141 std::cout <<
"[RieglProject] Warning: The scanposition '" << scan_dir
142 <<
"' has no scan data and therefore we gonna skip this scanposition." 149 std::string
transform = scanpos_info.second.get<std::string>(
"sop.matrix");
155 if (scanpos.images.empty()) {
156 std::cout <<
"[RieglProject] Warning: Scanposition '" << scan_dir
157 <<
"' has no images and will be skipped." << std::endl;
175 pt::ptree scanpos_ptree,
176 pt::ptree project_ptree) {
178 for (
auto img_info : scanpos_ptree.get_child(
"scanposimages")) {
179 if (img_info.first !=
"scanposimage")
continue;
183 std::string img_file = img_info.second.get<std::string>(
"file");
184 img.image_file = scanpos.scan_file.parent_path().parent_path() / (
"SCANPOSIMAGES/" + img_file);
187 if (!fs::exists(img.image_file) && !fs::is_regular_file(img.image_file)) {
188 std::cout <<
"[RieglProject] Warning: Image file '" << img.image_file
189 <<
"' doesn't exists or is not a regular file and there is skipped." 198 img.orientation_transform =
string2mat4f(img_info.second.get<std::string>(
"cop.matrix"));
205 std::string mountcalib_ref = img_info.second.get<std::string>(
"mountcalib_ref.<xmlattr>.noderef");
206 mountcalib_ref = mountcalib_ref.substr(mountcalib_ref.find_last_of(
'/') + 1);
208 bool found_mountcalib =
false;
209 for (
auto mountcalib_info : project_ptree.get_child(
"project.calibrations.mountcalibs")) {
210 if (mountcalib_info.first !=
"mountcalib")
continue;
211 if (mountcalib_info.second.get<std::string>(
"<xmlattr>.name") != mountcalib_ref)
continue;
213 found_mountcalib =
true;
215 img.extrinsic_transform =
string2mat4f(mountcalib_info.second.get<std::string>(
"matrix"));
219 if (!found_mountcalib) {
220 std::cout <<
"[RieglProject] Warning: Extrinsic transformation for image file '" 221 << img.image_file <<
"' wasn't found and image is gonna be skipped." 230 std::string camcalib_ref = img_info.second.get<std::string>(
"camcalib_ref.<xmlattr>.noderef");
231 camcalib_ref = camcalib_ref.substr(camcalib_ref.find_last_of(
'/') + 1);
233 bool found_camcalib =
false;
234 for (
auto camcalib_info : project_ptree.get_child(
"project.calibrations.camcalibs")) {
235 if (camcalib_info.first !=
"camcalib_opencv")
continue;
236 if (camcalib_info.second.get<std::string>(
"<xmlattr>.name") != camcalib_ref)
continue;
238 found_camcalib =
true;
240 pt::ptree intrinsic_ptree = camcalib_info.second.get_child(
"internal_opencv");
242 img.intrinsic_params[0] = intrinsic_ptree.get<
float>(
"fx");
243 img.intrinsic_params[1] = intrinsic_ptree.get<
float>(
"fy");
244 img.intrinsic_params[2] = intrinsic_ptree.get<
float>(
"cx");
245 img.intrinsic_params[3] = intrinsic_ptree.get<
float>(
"cy");
247 img.distortion_params[0] = intrinsic_ptree.get<
float>(
"k1");
248 img.distortion_params[1] = intrinsic_ptree.get<
float>(
"k2");
249 img.distortion_params[2] = intrinsic_ptree.get<
float>(
"k3");
250 img.distortion_params[3] = intrinsic_ptree.get<
float>(
"k4");
251 img.distortion_params[4] = intrinsic_ptree.get<
float>(
"p1");
252 img.distortion_params[5] = intrinsic_ptree.get<
float>(
"p2");
256 if (!found_camcalib) {
257 std::cout <<
"[RieglProject] Warning: Camcalibration for image file '" << img.image_file
258 <<
"' wasn't found and image is gonna be skipped." << std::endl;
263 scanpos.images.push_back(img);
272 if(!fs::exists(scans_path))
274 std::stringstream ss;
275 ss <<
"[RieglProject] Error: RiSCAN scans path '" << scans_path
276 <<
"' doesn't exist or isn't a directory";
277 throw fs::filesystem_error(
280 boost::system::errc::make_error_code(boost::system::errc::not_a_directory)
284 std::vector<fs::path> path_vec;
288 fs::directory_iterator{scans_path},
289 fs::directory_iterator{},
290 std::back_inserter(path_vec)
294 std::sort(path_vec.begin(), path_vec.end());
296 for(
int scan_id = 0; scan_id < path_vec.size(); scan_id ++)
298 fs::path cloud_path = path_vec[scan_id] /
"POINTCLOUDS";
300 if(!fs::exists(cloud_path))
302 std::stringstream ss;
303 ss <<
"[RieglProject] Error: RiSCAN cloud path '" << cloud_path
304 <<
"' doesn't exist or isn't a directory";
305 throw fs::filesystem_error(
308 boost::system::errc::make_error_code(boost::system::errc::not_a_directory)
312 std::vector<fs::path> potential_clouds;
315 fs::directory_iterator{cloud_path},
316 fs::directory_iterator{},
317 std::back_inserter(potential_clouds)
321 potential_clouds.begin(),
322 potential_clouds.end(),
323 [](
const fs::path& a,
const fs::path& b) {
324 return fs::file_size(a) > fs::file_size(b);
328 fs::path biggest_cloud_path = potential_clouds[0];
335 sp.scan_file = biggest_cloud_path;
345 std::cout <<
"[RieglProject] Error: RiSCAN project path '" <<
m_project_dir 346 <<
"' doesn't exist or isn't a directory" << std::endl;
353 if (!fs::exists(project_file) || !fs::is_regular_file(project_file)) {
354 std::cout <<
"[RieglProject] Error: The RiSCAN project file '" << project_file
355 <<
"' doesn't exist or isn't a file." << std::endl;
361 pt::ptree project_ptree;
362 pt::read_xml(project_file.string(), project_ptree);
367 std::cout <<
"[RieglProject] Error: Unable to parse any scanposition." << std::endl;
392 lhs <<
"Scan File: " << rhs.scan_file <<
" " 393 << fs::file_size(rhs.scan_file) <<
"\n" 397 for (ImageFile img : rhs.images) {
398 lhs <<
"\n\t" << img.image_file.filename() <<
" " << fs::file_size(img.image_file) <<
'\n' 399 <<
"Orientation: " << img.orientation_transform <<
'\n' 400 <<
"Extrinsic: " << img.extrinsic_transform <<
'\n';
402 lhs <<
"Intrinsic: ";
403 for (
int i = 0; i < 4; i++) {
404 lhs << img.intrinsic_params[i] <<
" ";
407 lhs <<
'\n' <<
"Distortion: ";
408 for (
int i = 0; i < 6; i++) {
409 lhs << img.distortion_params[i] <<
" ";
std::ostream & operator<<(std::ostream &os, const BaseVector< T > &v)
std::string m_input_cloud_format
void parse_scanpositions(pt::ptree project_ptree, unsigned int start, unsigned int end)
Transformd string2mat4f(const std::string data)
Transform< double > Transformd
4x4 double precision transformation matrix
std::vector< ScanPosition > m_scan_positions
void parse_images_per_scanpos(ScanPosition &scanpos, pt::ptree scanpos_ptree, pt::ptree project_ptree)
Transform< T > buildTransformation(T *alignxf)
Transforms an slam6d transformation matrix into an Eigen 4x4 matrix.
RieglProject(std::string dir, std::string input_cloud_format="rxp")
Construct a new Riegl Project object.
bool parse_project(unsigned int start, unsigned int end)
std::string get_first_group_regex(std::regex regex_string, std::string data)