/* * scan_io_rts implementation * * Copyright (C) Thomas Escher, Kai Lingemann, Andreas Nuechter * * Released under the GPL version 3. * */ /** * @file * @brief Implementation of reading 3D scans * @author Kai Lingemann. Institute of Computer Science, University of Osnabrueck, Germany. * @author Andreas Nuechter. Institute of Computer Science, University of Osnabrueck, Germany. * @author Thomas Escher */ #include "scanio/scan_io_rts.h" #include using std::cout; using std::cerr; using std::endl; #include using std::vector; #include using std::stringstream; #ifdef _MSC_VER #include #endif #include #include using namespace boost::filesystem; #include "slam6d/globals.icc" #define DATA_PATH_PREFIX "scan3d_0_" #define DATA_PATH_SUFFIX ".3d" #define POSE_PATH_FILE "odometry_0_sync_interpol.dat" //! RTS type flag for invalid points #define TYPE_INVALID 0x10 std::list ScanIO_rts::readDirectory(const char* dir_path, unsigned int start, unsigned int end) { std::list identifiers; // only a single pose file, can't do without one path pose_path(dir_path); pose_path /= POSE_PATH_FILE; if(exists(pose_path)) { for(unsigned int i = start; i <= end; ++i) { // identifier is a number (0-\infty) std::string identifier(to_string(i)); // scan consists of data (.3d) files path data(dir_path); data /= path(std::string(DATA_PATH_PREFIX) + identifier + DATA_PATH_SUFFIX); // stop if part of a scan is missing or end by absence is detected if(!exists(data)) break; identifiers.push_back(identifier); } } return identifiers; } void ScanIO_rts::readPose(const char* dir_path, const char* identifier, double* pose) { unsigned int i; // if directory doesn't match the cached one, rebuild pose cache if(cached_dir != dir_path) { // check for pose file path pose_path(dir_path); pose_path /= POSE_PATH_FILE; if(!exists(pose_path)) throw std::runtime_error(std::string("There is no pose file in [") + dir_path + "]"); // open pose file once and read all poses ifstream pose_file(pose_path); pose_file.exceptions(ifstream::eofbit|ifstream::failbit|ifstream::badbit); vector poses; double p[6], timestamp; while(pose_file.good()) { try { pose_file >> timestamp >> p[2] >> p[0] >> p[1] // x, y, z >> p[3] >> p[5] >> p[4]; // theta_x, theta_y, theta_z } catch(std::ios_base::failure& e) { break; } // convert for(i = 0; i < 3; ++i) p[i] *= 0.1; // add in poses for(i = 0; i < 6; ++i) poses.push_back(p[i]); } // after success, set the cache cached_poses.swap(poses); cached_dir = dir_path; } // get index from the identifier and pick the pose stringstream str(identifier); unsigned int scan_index; str >> scan_index; if(cached_poses.size() < scan_index*6 + 6) throw std::runtime_error(std::string("There is no pose entry for scan [") + identifier + "]"); for(i = 0; i < 6; ++i) pose[i] = cached_poses[scan_index*6 + i]; return; } bool ScanIO_rts::supports(IODataType type) { return !!(type & (DATA_XYZ)); } void ScanIO_rts::readScan(const char* dir_path, const char* identifier, PointFilter& filter, std::vector* xyz, std::vector* rgb, std::vector* reflectance, std::vector* temperature, std::vector* amplitude, std::vector* type, std::vector* deviation) { // TODO: Type and other columns? unsigned int i; // error handling path data_path(dir_path); data_path /= path(std::string(DATA_PATH_PREFIX) + identifier + DATA_PATH_SUFFIX); if(!exists(data_path)) throw std::runtime_error(std::string("There is no scan file for [") + identifier + "] in [" + dir_path + "]"); if(xyz != 0) { // open data file ifstream data_file(data_path); data_file.exceptions(ifstream::eofbit|ifstream::failbit|ifstream::badbit); // read points // z x y type ? ? double point[3]; int type, dummy; while(data_file.good()) { try { data_file >> point[2] >> point[0] >> point[1]; data_file >> type >> dummy >> dummy; } catch(std::ios_base::failure& e) { break; } // convert point[0] *= 0.1; point[1] *= -0.1; point[2] *= 0.1; // apply filter and insert point if(!(type & TYPE_INVALID)) { if(filter.check(point)) { for(i = 0; i < 3; ++i) xyz->push_back(point[i]); } } } data_file.close(); } } /** * class factory for object construction * * @return Pointer to new object */ #ifdef _MSC_VER extern "C" __declspec(dllexport) ScanIO* create() #else extern "C" ScanIO* create() #endif { return new ScanIO_rts; } /** * class factory for object construction * * @return Pointer to new object */ #ifdef _MSC_VER extern "C" __declspec(dllexport) void destroy(ScanIO *sio) #else extern "C" void destroy(ScanIO *sio) #endif { delete sio; } #ifdef _MSC_VER BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved) { return TRUE; } #endif