/* * managedScan implementation * * Copyright (C) Kai Lingemann, Thomas Escher * * Released under the GPL version 3. * */ #include "slam6d/managedScan.h" #include "scanserver/clientInterface.h" #include "slam6d/Boctree.h" #include "slam6d/kdManaged.h" #ifdef WITH_METRICS #include "slam6d/metrics.h" #endif //WITH_METRICS #include using std::stringstream; #include using namespace boost::filesystem; SharedScanVector* ManagedScan::shared_scans = 0; void ManagedScan::openDirectory(const std::string& path, IOType type, int start, int end) { // start the client first try { ClientInterface::create(); } catch(std::runtime_error& e) { cerr << "ClientInterface could not be created: " << e.what() << endl; cerr << "Start the scanserver first." << endl; exit(-1); } #ifdef WITH_METRICS Timer t = ClientMetric::read_scan_time.start(); #endif //WITH_METRICS ClientInterface* client = ClientInterface::getInstance(); shared_scans = client->readDirectory(path.c_str(), type, start, end); for(SharedScanVector::iterator it = shared_scans->begin(); it != shared_scans->end(); ++it) { // add a scan with reference on the shared scan SharedScan* shared = it->get(); ManagedScan* scan = new ManagedScan(shared); Scan::allScans.push_back(scan); } #ifdef WITH_METRICS ClientMetric::read_scan_time.end(t); #endif //WITH_METRICS } void ManagedScan::closeDirectory() { // clean up the scan vector for(std::vector::iterator it = Scan::allScans.begin(); it != Scan::allScans.end(); ++it) delete *it; allScans.clear(); // remove the shared scan vector ClientInterface* client = ClientInterface::getInstance(); #ifdef WITH_METRICS ClientInterface::getInstance()->printMetrics(); #endif //WITH_METRICS client->closeDirectory(shared_scans); } std::size_t ManagedScan::getMemorySize() { ClientInterface* client = ClientInterface::getInstance(); return client->getCacheSize(); } ManagedScan::ManagedScan(SharedScan* shared_scan) : m_shared_scan(shared_scan), m_reduced_ready(false), m_reset_frames_on_write(true) { // request pose from the shared scan double* euler = m_shared_scan->getPose(); rPos[0] = euler[0]; rPos[1] = euler[1]; rPos[2] = euler[2]; rPosTheta[0] = euler[3]; rPosTheta[1] = euler[4]; rPosTheta[2] = euler[5]; // write original pose matrix EulerToMatrix4(euler, &euler[3], transMatOrg); // initialize transform matrices from the original one, could just copy transMatOrg to transMat instead transformMatrix(transMatOrg); // reset the delta align matrix to represent only the transformations after local-to-global (transMatOrg) one M4identity(dalignxf); } ManagedScan::~ManagedScan() { // TODO: something to do? } void ManagedScan::setRangeFilter(double max, double min) { m_shared_scan->setRangeParameters(max, min); } void ManagedScan::setHeightFilter(double top, double bottom) { m_shared_scan->setHeightParameters(top, bottom); } void ManagedScan::setRangeMutation(double range) { m_shared_scan->setRangeMutationParameters(range); } void ManagedScan::setReductionParameter(double voxelSize, int nrpts, PointType pointtype) { Scan::setReductionParameter(voxelSize, nrpts, pointtype); // set parameters to invalidate old cache data stringstream s; s << voxelSize << " " << nrpts << " " << transMatOrg; m_shared_scan->setReductionParameters(s.str().c_str()); } void ManagedScan::setShowReductionParameter(double voxelSize, int nrpts, PointType pointtype) { show_reduction_voxelSize = voxelSize; show_reduction_nrpts = nrpts; show_reduction_pointtype = pointtype; // set parameters to invalidate old cache data stringstream s; s << voxelSize << " " << nrpts; m_shared_scan->setShowReductionParameters(s.str().c_str()); } void ManagedScan::setOcttreeParameter(double reduction_voxelSize, double octtree_voxelSize, PointType pointtype, bool loadOct, bool saveOct) { Scan::setOcttreeParameter(reduction_voxelSize, octtree_voxelSize, pointtype, loadOct, saveOct); // set octtree parameters to invalidate cached ones with other parameters (changing range/height is already handled) stringstream s; s << reduction_voxelSize << " " << octtree_voxelSize << " " << pointtype.toFlags(); m_shared_scan->setOcttreeParameters(s.str().c_str()); } DataPointer ManagedScan::get(const std::string& identifier) { if(identifier == "xyz") { return m_shared_scan->getXYZ(); } else if(identifier == "rgb") { return m_shared_scan->getRGB(); } else if(identifier == "reflectance") { return m_shared_scan->getReflectance(); } else if(identifier == "temperature") { return m_shared_scan->getTemperature(); } else if(identifier == "amplitude") { return m_shared_scan->getAmplitude(); } else if(identifier == "type") { return m_shared_scan->getType(); } else if(identifier == "deviation") { return m_shared_scan->getDeviation(); } else if(identifier == "xyz reduced") { // if this is a fresh run, initialize reduced properly via original or creating it anew if(!m_reduced_ready) { calcReducedOnDemand(); } return m_shared_scan->getXYZReduced(); } else if(identifier == "xyz reduced original") { // if reduction has completed, original will exist (either from last run or created in this run) if(!m_reduced_ready) { calcReducedOnDemand(); } return m_shared_scan->getXYZReducedOriginal(); } else if(identifier == "xyz reduced show") { if(m_shared_scan->getXYZReducedShow().valid()) return m_shared_scan->getXYZReducedShow(); calcReducedShow(); return m_shared_scan->getXYZReducedShow(); } else if(identifier == "octtree") { if(m_shared_scan->getOcttree().valid()) return m_shared_scan->getOcttree(); createOcttree(); return m_shared_scan->getOcttree(); } { throw runtime_error(string("Identifier '") + identifier + "' not compatible with ManagedScan::get. Upgrade SharedScan for this data field."); } } void ManagedScan::get(unsigned int types) { m_shared_scan->prefetch(types); } DataPointer ManagedScan::create(const std::string& identifier, unsigned int size) { // map identifiers to functions in SharedScan and scale back size from bytes to number of points if(identifier == "xyz reduced") { return m_shared_scan->createXYZReduced(size / (3*sizeof(double))); } else if(identifier == "xyz reduced original") { return m_shared_scan->createXYZReducedOriginal(size / (3*sizeof(double))); } else if(identifier == "reflectance") { return m_shared_scan->createReflectance(size / (1*sizeof(double))); } else { throw runtime_error(string("Identifier '") + identifier + "' not compatible with ManagedScan::create. Upgrade SharedScan for this data field."); } } void ManagedScan::clear(const std::string& identifier) { // nothing to do here // TODO: mark CacheObjects with a low priority for faster removal by the manager } void ManagedScan::createSearchTreePrivate() { switch(searchtree_nnstype) { case simpleKD: kd = new KDtreeManaged(this); break; case BOCTree: kd = new BOctTree(PointerArray(get("xyz reduced original")).get(), size("xyz reduced original"), 10.0, PointType(), true); break; case -1: throw runtime_error("Cannot create a SearchTree without setting a type."); default: throw runtime_error("SearchTree type not implemented for ManagedScan"); } // TODO: look into CUDA compability } void ManagedScan::calcReducedOnDemandPrivate() { // either copy from original or create them like BasicScan DataXYZ xyz_orig(m_shared_scan->getXYZReducedOriginal()); if(xyz_orig.valid()) { // set true to inform further get("xyz reduced original") calls to get the data instead of looping calcReducedOnDemand m_reduced_ready = true; copyOriginalToReduced(); } else { // create reduced points and transform to initial position, save a copy of this for SearchTree calcReducedPoints(); // set true to inform further get("xyz reduced") calls to get the data instead of looping calcReducedOnDemand m_reduced_ready = true; transformReduced(transMatOrg); copyReducedToOriginal(); } } void ManagedScan::calcReducedShow() { // create an octtree reduction from full points DataXYZ xyz(get("xyz")); BOctTree* oct = new BOctTree(PointerArray(xyz).get(), xyz.size(), show_reduction_voxelSize); vector center; center.clear(); if(show_reduction_nrpts > 0) { if(show_reduction_nrpts == 1) { oct->GetOctTreeRandom(center); } else { oct->GetOctTreeRandom(center, show_reduction_nrpts); } } else { oct->GetOctTreeCenter(center); } unsigned int size = center.size(); TripleArray xyz_r(m_shared_scan->createXYZReducedShow(size)); for(unsigned int i = 0; i < size; ++i) { for(unsigned int j = 0; j < 3; ++j) { xyz_r[i][j] = center[i][j]; } } delete oct; } void ManagedScan::createOcttree() { string scanFileName = string(m_shared_scan->getDirPath()) + "scan" + getIdentifier() + ".oct"; BOctTree* btree = 0; // if loadOct is given, load the octtree under blind assumption that parameters match if(octtree_loadOct && exists(scanFileName)) { btree = new BOctTree(scanFileName); } else { if(octtree_reduction_voxelSize > 0) { // with reduction, only xyz points TripleArray xyz_r(get("xyz reduced show")); btree = new BOctTree(PointerArray(xyz_r).get(), xyz_r.size(), octtree_voxelSize, octtree_pointtype, true); } else { // without reduction, xyz + attribute points float** pts = octtree_pointtype.createPointArray(this); unsigned int nrpts = size("xyz"); btree = new BOctTree(pts, nrpts, octtree_voxelSize, octtree_pointtype, true); for(unsigned int i = 0; i < nrpts; ++i) delete[] pts[i]; delete[] pts; } // save created octtree if(octtree_saveOct) { cout << "Saving octree " << scanFileName << endl; btree->serialize(scanFileName); } } // copy tree into cache try { unsigned int size = btree->getMemorySize(); unsigned char* mem_ptr = m_shared_scan->createOcttree(size).get_raw_pointer(); new(mem_ptr) BOctTree(*btree, mem_ptr, size); delete btree; btree = 0; } catch(runtime_error& e) { // delete tree if copy to cache failed delete btree; throw e; } } unsigned int ManagedScan::readFrames() { // automatically read on getFrames return m_shared_scan->getFrames().size(); } void ManagedScan::saveFrames() { m_shared_scan->saveFrames(); } unsigned int ManagedScan::getFrameCount() { return m_shared_scan->getFrames().size(); } void ManagedScan::getFrame(unsigned int i, const double*& pose_matrix, AlgoType& type) { const Frame& frame(m_shared_scan->getFrames().at(i)); pose_matrix = frame.transformation; type = static_cast(frame.type); } void ManagedScan::addFrame(AlgoType type) { if(m_reset_frames_on_write) { m_shared_scan->clearFrames(); m_reset_frames_on_write = false; } m_shared_scan->addFrame(transMat, static_cast(type)); }