/* * exportPoints implementation * * Copyright (C) Jochen Sprickerhof * * Released under the GPL version 3. * */ /** * @file * @author Jochen Sprickerhof. Institute of Computer Science, University of Osnabrueck, Germany. */ #include using std::string; #include using std::cout; using std::cerr; using std::endl; #include using std::ifstream; #include using std::exception; #include #include #include "slam6d/scan.h" #include "slam6d/globals.icc" #ifndef _MSC_VER #include #else #include "XGetopt.h" #endif #ifdef _MSC_VER #define strcasecmp _stricmp #define strncasecmp _strnicmp #else #include #endif /** * Explains the usage of this program's command line parameters */ void usage(char* prog) { #ifndef _MSC_VER const string bold("\033[1m"); const string normal("\033[m"); #else const string bold(""); const string normal(""); #endif cout << endl << bold << "USAGE " << normal << endl << " " << prog << " [options] directory" << endl << endl; cout << bold << "OPTIONS" << normal << endl << endl << bold << " -e" << normal << " NR, " << bold << "--end=" << normal << "NR" << endl << " end after scan NR" << endl << endl << bold << " -f" << normal << " F, " << bold << "--format=" << normal << "F" << endl << " using shared library F for input" << endl << " (chose F from {uos, uos_map, uos_rgb, uos_frames, uos_map_frames, old, rts, rts_map, ifp, riegl_txt, riegl_rgb, riegl_bin, zahn, ply})" << endl << endl << bold << " -m" << normal << " NR, " << bold << "--max=" << normal << "NR" << endl << " neglegt all data points with a distance larger than NR 'units'" << endl << endl << bold << " -M" << normal << " NR, " << bold << "--min=" << normal << "NR" << endl << " neglegt all data points with a distance smaller than NR 'units'" << endl << endl << bold << " -O" << normal << " NR (optional), " << bold << "--octree=" << normal << "NR (optional)" << endl << " use randomized octree based point reduction (pts per voxel=)" << endl << " requires -r or --reduce" << endl << endl << bold << " -p, --trustpose" << normal << endl << " Trust the pose file, do not extrapolate the last transformation." << endl << " (just for testing purposes, or gps input.)" << endl << endl << endl << bold << " -r" << normal << " NR, " << bold << "--reduce=" << normal << "NR" << endl << " turns on octree based point reduction (voxel size=)" << endl << endl << bold << " -R" << normal << " NR, " << bold << "--random=" << normal << "NR" << endl << " turns on randomized reduction, using about every -th point only" << endl << endl << bold << " -s" << normal << " NR, " << bold << "--start=" << normal << "NR" << endl << " start at scan NR (i.e., neglects the first NR scans)" << endl << " [ATTENTION: counting naturally starts with 0]" << endl << endl << endl << endl; cout << bold << "EXAMPLES " << normal << endl << " " << prog << " -s 2 -e 3 dat" << endl << endl; exit(1); } /** A function that parses the command-line arguments and sets the respective flags. * @param argc the number of arguments * @param argv the arguments * @param dir the directory * @param red using point reduction? * @param rand use randomized point reduction? * @param mdm maximal distance match * @param mdml maximal distance match for SLAM * @param mni maximal number of iterations * @param start starting at scan number 'start' * @param end stopping at scan number 'end' * @param maxDist - maximal distance of points being loaded * @param minDist - minimal distance of points being loaded * @param quiet switches on/off the quiet mode * @param veryQuiet switches on/off the 'very quiet' mode * @param extrapolate_pose - i.e., extrapolating the odometry by the last transformation * (vs. taking the pose file as exact) * @param meta match against all scans (= meta scan), or against the last scan only??? * @param anim selects the rotation representation for the matching algorithm * @param mni_lum sets the maximal number of iterations for SLAM * @param net specifies the file that includes the net structure for SLAM * @param cldist specifies the maximal distance for closed loops * @param epsilonICP stop ICP iteration if difference is smaller than this value * @param epsilonSLAM stop SLAM iteration if average difference is smaller than this value * @param algo specfies the used algorithm for rotation computation * @param lum6DAlgo specifies the used algorithm for global SLAM correction * @param loopsize defines the minimal loop size * @return 0, if the parsing was successful. 1 otherwise */ int parseArgs(int argc, char **argv, string &dir, double &red, int &rand, int &start, int &end, int &maxDist, int &minDist, bool &extrapolate_pose, int &octree, IOType &type) { int c; // from unistd.h: extern char *optarg; extern int optind; /* options descriptor */ // 0: no arguments, 1: required argument, 2: optional argument static struct option longopts[] = { { "format", required_argument, 0, 'f' }, { "start", required_argument, 0, 's' }, { "end", required_argument, 0, 'e' }, { "reduce", required_argument, 0, 'r' }, { "octree", optional_argument, 0, 'O' }, { "random", required_argument, 0, 'R' }, { "trustpose", no_argument, 0, 'p' }, { 0, 0, 0, 0} // needed, cf. getopt.h }; cout << endl; while ((c = getopt_long(argc, argv, "f:s:e:r:O:R:p", longopts, NULL)) != -1) switch (c) { case 'r': red = atof(optarg); break; case 'O': if (optarg) { octree = atoi(optarg); } else { octree = 1; } break; case 'R': rand = atoi(optarg); break; case 's': start = atoi(optarg); if (start < 0) { cerr << "Error: Cannot start at a negative scan number.\n"; exit(1); } break; case 'e': end = atoi(optarg); if (end < 0) { cerr << "Error: Cannot end at a negative scan number.\n"; exit(1); } if (end < start) { cerr << "Error: cannot be smaller than .\n"; exit(1); } break; case 'm': maxDist = atoi(optarg); break; case 'M': minDist = atoi(optarg); break; case 'p': extrapolate_pose = false; break; case 'f': try { type = formatname_to_io_type(optarg); } catch (...) { // runtime_error cerr << "Format " << optarg << " unknown." << endl; abort(); } break; case '?': usage(argv[0]); return 1; default: abort (); } if (optind != argc-1) { cerr << "\n*** Directory missing ***" << endl; usage(argv[0]); } dir = argv[optind]; #ifndef _MSC_VER if (dir[dir.length()-1] != '/') dir = dir + "/"; #else if (dir[dir.length()-1] != '\\') dir = dir + "\\"; #endif return 0; } void readFrames(string dir, int start, int end, IOType &type) { ifstream frame_in; int fileCounter = start; string frameFileName; for (;;) { if (end > -1 && fileCounter > end) break; // 'nuf read frameFileName = dir + "scan" + to_string(fileCounter++,3) + ".frames"; frame_in.open(frameFileName.c_str()); // read 3D scan if (!frame_in.good()) break; // no more files in the directory cout << "Reading Frames for 3D Scan " << frameFileName << "..." << endl; // vector Matrices; // vector algoTypes; double transMat[16]; int algoTypeInt; while (frame_in.good()) { try { frame_in >> transMat >> algoTypeInt; } catch (const exception &e) { break; } } if(type == UOS_MAP || type == UOS_MAP_FRAMES || type == RTS_MAP) { Scan::allScans[fileCounter - start]->transformAll(transMat); if(fileCounter == start+1) { Scan::allScans[0]->transformAll(transMat); } } else { Scan::allScans[fileCounter - start - 1]->transformAll(transMat); } frame_in.close(); frame_in.clear(); } } /** * program for point export * Usage: bin/exportPoints 'dir', * with 'dir' the directory of a set of scans * ... */ int main(int argc, char **argv) { if (argc <= 1) { usage(argv[0]); } // parsing the command line parameters // init, default values if not specified string dir; double red = -1.0; int rand = -1; int start = 0, end = -1; int maxDist = -1; int minDist = -1; bool eP = true; // should we extrapolate the pose?? int octree = 0; // employ randomized octree reduction? IOType type = UOS; // parseArgs(argc, argv, dir, red, rand, start, end, // maxDist, minDist, eP, octree, type); // // // Get Scans // Scan::readScans(type, start, end, dir, maxDist, minDist, true); // // int end_reduction = (int)Scan::allScans.size(); //#ifdef _OPENMP //#pragma omp parallel for schedule(dynamic) //#endif // for (int iterator = 0; iterator < end_reduction; iterator++) { // if (red > 0) { // cout << "Reducing Scan No. " << iterator << endl; // } else { // cout << "Copying Scan No. " << iterator << endl; // } // // reduction filter for current scan! // Scan::allScans[iterator]->calcReducedPoints(red, octree); // } // // if(eP) { // readFrames(dir, start, end, type); // } // // cout << "Export all 3D Points to file \"points.pts\"" << endl; // ofstream redptsout("points.pts"); // for(unsigned int i = 0; i < Scan::allScans.size(); i++) { // const vector *points = Scan::allScans[i]->get_points(); // for(unsigned int j = 0; j < points->size(); j++) { // redptsout << points->at(j) << endl; // } // } // redptsout.close(); // redptsout.clear(); }