From 71b639301851bf21cd00811f00d77a30d54238f7 Mon Sep 17 00:00:00 2001 From: Tobias Fischer Date: Fri, 8 May 2026 05:45:51 +1000 Subject: [PATCH 1/2] Fixes for compilation on MacOS --- Examples/Monocular/vslamlab_orbslam2_mono.cpp | 3 +-- Examples/RGB-D/vslamlab_orbslam2_rgbd.cpp | 3 +-- Examples/Stereo/vslamlab_orbslam2_stereo.cpp | 3 +-- Thirdparty/DBoW2/DBoW2/FORB.cpp | 3 +-- Thirdparty/g2o/g2o/core/estimate_propagator.h | 6 +++++- Thirdparty/g2o/g2o/core/hyper_graph.h | 6 +++++- .../g2o/g2o/core/marginal_covariance_cholesky.h | 8 ++++++-- Thirdparty/g2o/g2o/core/robust_kernel.h | 6 +++++- Thirdparty/g2o/g2o/core/sparse_block_matrix_ccs.h | 6 +++++- build.sh | 15 ++++++++------- src/ORBmatcher.cc | 2 +- 11 files changed, 39 insertions(+), 22 deletions(-) diff --git a/Examples/Monocular/vslamlab_orbslam2_mono.cpp b/Examples/Monocular/vslamlab_orbslam2_mono.cpp index b5b8db7502..be69b2e79d 100644 --- a/Examples/Monocular/vslamlab_orbslam2_mono.cpp +++ b/Examples/Monocular/vslamlab_orbslam2_mono.cpp @@ -5,8 +5,7 @@ #include #include -#include "sys/types.h" -#include "sys/sysinfo.h" +#include #include diff --git a/Examples/RGB-D/vslamlab_orbslam2_rgbd.cpp b/Examples/RGB-D/vslamlab_orbslam2_rgbd.cpp index 95e16595b5..e4e37581f8 100644 --- a/Examples/RGB-D/vslamlab_orbslam2_rgbd.cpp +++ b/Examples/RGB-D/vslamlab_orbslam2_rgbd.cpp @@ -4,8 +4,7 @@ #include #include -#include "sys/types.h" -#include "sys/sysinfo.h" +#include #include diff --git a/Examples/Stereo/vslamlab_orbslam2_stereo.cpp b/Examples/Stereo/vslamlab_orbslam2_stereo.cpp index 69083794c1..769724960a 100644 --- a/Examples/Stereo/vslamlab_orbslam2_stereo.cpp +++ b/Examples/Stereo/vslamlab_orbslam2_stereo.cpp @@ -4,8 +4,7 @@ #include #include -#include "sys/types.h" -#include "sys/sysinfo.h" +#include #include diff --git a/Thirdparty/DBoW2/DBoW2/FORB.cpp b/Thirdparty/DBoW2/DBoW2/FORB.cpp index 1f1990c2f7..0dc07dfd5d 100644 --- a/Thirdparty/DBoW2/DBoW2/FORB.cpp +++ b/Thirdparty/DBoW2/DBoW2/FORB.cpp @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include "FORB.h" @@ -190,4 +190,3 @@ void FORB::toMat8U(const std::vector &descriptors, } // namespace DBoW2 - diff --git a/Thirdparty/g2o/g2o/core/estimate_propagator.h b/Thirdparty/g2o/g2o/core/estimate_propagator.h index 6a16d11d3a..e5589bde0e 100644 --- a/Thirdparty/g2o/g2o/core/estimate_propagator.h +++ b/Thirdparty/g2o/g2o/core/estimate_propagator.h @@ -34,7 +34,7 @@ #include #include -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__APPLE__) #include #else #include @@ -135,7 +135,11 @@ namespace g2o { size_t operator ()(const OptimizableGraph::Vertex* v) const { return v->id();} }; +#if defined(_MSC_VER) || defined(__APPLE__) + typedef std::unordered_map AdjacencyMap; +#else typedef std::tr1::unordered_map AdjacencyMap; +#endif public: EstimatePropagator(OptimizableGraph* g); diff --git a/Thirdparty/g2o/g2o/core/hyper_graph.h b/Thirdparty/g2o/g2o/core/hyper_graph.h index da6bb3d361..df4ee96f25 100644 --- a/Thirdparty/g2o/g2o/core/hyper_graph.h +++ b/Thirdparty/g2o/g2o/core/hyper_graph.h @@ -35,7 +35,7 @@ #include #include -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__APPLE__) #include #else #include @@ -90,7 +90,11 @@ namespace g2o { typedef std::set EdgeSet; typedef std::set VertexSet; +#if defined(_MSC_VER) || defined(__APPLE__) + typedef std::unordered_map VertexIDMap; +#else typedef std::tr1::unordered_map VertexIDMap; +#endif typedef std::vector VertexContainer; //! abstract Vertex, your types must derive from that one diff --git a/Thirdparty/g2o/g2o/core/marginal_covariance_cholesky.h b/Thirdparty/g2o/g2o/core/marginal_covariance_cholesky.h index e7dfce88f8..ef1342116c 100644 --- a/Thirdparty/g2o/g2o/core/marginal_covariance_cholesky.h +++ b/Thirdparty/g2o/g2o/core/marginal_covariance_cholesky.h @@ -33,7 +33,7 @@ #include #include -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__APPLE__) #include #else #include @@ -50,8 +50,12 @@ namespace g2o { /** * hash struct for storing the matrix elements needed to compute the covariance */ +#if defined(_MSC_VER) || defined(__APPLE__) + typedef std::unordered_map LookupMap; +#else typedef std::tr1::unordered_map LookupMap; - +#endif + public: MarginalCovarianceCholesky(); ~MarginalCovarianceCholesky(); diff --git a/Thirdparty/g2o/g2o/core/robust_kernel.h b/Thirdparty/g2o/g2o/core/robust_kernel.h index 29e1394a0d..529d6b5ea6 100644 --- a/Thirdparty/g2o/g2o/core/robust_kernel.h +++ b/Thirdparty/g2o/g2o/core/robust_kernel.h @@ -27,7 +27,7 @@ #ifndef G2O_ROBUST_KERNEL_H #define G2O_ROBUST_KERNEL_H -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__APPLE__) #include #else #include @@ -74,7 +74,11 @@ namespace g2o { protected: double _delta; }; +#if defined(_MSC_VER) || defined(__APPLE__) + typedef std::shared_ptr RobustKernelPtr; +#else typedef std::tr1::shared_ptr RobustKernelPtr; +#endif } // end namespace g2o diff --git a/Thirdparty/g2o/g2o/core/sparse_block_matrix_ccs.h b/Thirdparty/g2o/g2o/core/sparse_block_matrix_ccs.h index eb9042c218..095a520e1e 100644 --- a/Thirdparty/g2o/g2o/core/sparse_block_matrix_ccs.h +++ b/Thirdparty/g2o/g2o/core/sparse_block_matrix_ccs.h @@ -34,7 +34,7 @@ #include "../../config.h" #include "matrix_operations.h" -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__APPLE__) #include #else #include @@ -223,7 +223,11 @@ namespace g2o { //! rows of the matrix int rows() const {return _rowBlockIndices.size() ? _rowBlockIndices.back() : 0;} +#if defined(_MSC_VER) || defined(__APPLE__) + typedef std::unordered_map SparseColumn; +#else typedef std::tr1::unordered_map SparseColumn; +#endif SparseBlockMatrixHashMap(const std::vector& rowIndices, const std::vector& colIndices) : _rowBlockIndices(rowIndices), _colBlockIndices(colIndices) diff --git a/build.sh b/build.sh index d55e11ff21..dd52e44c4a 100755 --- a/build.sh +++ b/build.sh @@ -1,4 +1,5 @@ #!/bin/bash +set -euo pipefail delete_if_exists() { local folder=$1 @@ -27,17 +28,17 @@ build_library() { lib_folder="$source_folder/lib" if [ "$force_build" = true ]; then - delete_if_exists ${source_folder} + delete_if_exists "${source_folder}" fi if [ "$verbose" = true ]; then echo "[${library_name}][build.sh] Compile ${library_name} ... " - cmake -G Ninja -B $build_folder -S $source_folder -DCMAKE_PREFIX_PATH=$source_folder -DCMAKE_INSTALL_PREFIX=$source_folder - cmake --build $build_folder --config Release + cmake -G Ninja -B "$build_folder" -S "$source_folder" -DCMAKE_PREFIX_PATH="$source_folder" -DCMAKE_INSTALL_PREFIX="$source_folder" + cmake --build "$build_folder" --config Release else echo "[${library_name}][build.sh] Compile ${library_name} (output disabled) ... " - cmake -G Ninja -B $build_folder -S $source_folder -DCMAKE_PREFIX_PATH=$source_folder -DCMAKE_INSTALL_PREFIX=$source_folder > /dev/null 2>&1 - cmake --build $build_folder --config Release > /dev/null 2>&1 + cmake -G Ninja -B "$build_folder" -S "$source_folder" -DCMAKE_PREFIX_PATH="$source_folder" -DCMAKE_INSTALL_PREFIX="$source_folder" > /dev/null 2>&1 + cmake --build "$build_folder" --config Release > /dev/null 2>&1 fi } @@ -60,7 +61,7 @@ done # Baseline Dir LIBRARY_PATH=$(realpath "$0") -LIBRARY_DIR=$(dirname "LIBRARY_PATH") +LIBRARY_DIR=$(dirname "$LIBRARY_PATH") ## Build ORB-SLAM2 library_name="ORB-SLAM2" @@ -72,4 +73,4 @@ echo "[${library_name}][build.sh] Uncompress vocabulary ... " vocabulary_folder="${LIBRARY_DIR}/Vocabulary" if [ ! -f "${vocabulary_folder}/ORBvoc.txt" ]; then tar -xf "${LIBRARY_DIR}/Vocabulary/ORBvoc.txt.tar.gz" -C "${LIBRARY_DIR}/Vocabulary" -fi \ No newline at end of file +fi diff --git a/src/ORBmatcher.cc b/src/ORBmatcher.cc index 56bf279d0f..0f1b8aea0d 100644 --- a/src/ORBmatcher.cc +++ b/src/ORBmatcher.cc @@ -27,7 +27,7 @@ #include "Thirdparty/DBoW2/DBoW2/FeatureVector.h" -#include +#include using namespace std; From a77ae974775665b77aa06ba0c9b3508727086214 Mon Sep 17 00:00:00 2001 From: Tobias Fischer Date: Fri, 8 May 2026 07:09:23 +1000 Subject: [PATCH 2/2] Fix threading issue on osx --- Examples/Monocular/vslamlab_orbslam2_mono.cpp | 87 +++++++++------- Examples/RGB-D/vslamlab_orbslam2_rgbd.cpp | 89 ++++++++++------- Examples/Stereo/vslamlab_orbslam2_stereo.cpp | 99 +++++++++++-------- include/System.h | 6 ++ src/System.cc | 25 ++++- 5 files changed, 187 insertions(+), 119 deletions(-) diff --git a/Examples/Monocular/vslamlab_orbslam2_mono.cpp b/Examples/Monocular/vslamlab_orbslam2_mono.cpp index be69b2e79d..88cd1f9943 100644 --- a/Examples/Monocular/vslamlab_orbslam2_mono.cpp +++ b/Examples/Monocular/vslamlab_orbslam2_mono.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -115,51 +116,63 @@ int main(int argc, char **argv) cout << "Start processing sequence ..." << endl; cout << "Images in the sequence: " << nImages << endl << endl; - // Main loop - cv::Mat im; - for(size_t ni = 0; ni < nImages; ni++) - { - // Read image from file - im = cv::imread(imageFilenames[ni],cv::IMREAD_UNCHANGED); - ORB_SLAM2::Seconds tframe = timestamps[ni]; + auto processSequence = [&]() { + cv::Mat im; + for(size_t ni = 0; ni < nImages; ni++) + { + // Read image from file + im = cv::imread(imageFilenames[ni],cv::IMREAD_UNCHANGED); + ORB_SLAM2::Seconds tframe = timestamps[ni]; - // Pass the image to the SLAM system - std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now(); - SLAM.TrackMonocular(im,tframe); - std::chrono::steady_clock::time_point t2 = std::chrono::steady_clock::now(); + // Pass the image to the SLAM system + std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now(); + SLAM.TrackMonocular(im,tframe); + std::chrono::steady_clock::time_point t2 = std::chrono::steady_clock::now(); - ORB_SLAM2::Seconds ttrack = std::chrono::duration_cast >(t2 - t1).count(); - vTimesTrack[ni] = ttrack; + ORB_SLAM2::Seconds ttrack = std::chrono::duration_cast >(t2 - t1).count(); + vTimesTrack[ni] = ttrack; - // Wait to load the next frame - ORB_SLAM2::Seconds T = 0.0; - if(ni < nImages-1) - T = timestamps[ni+1] - tframe; - else if(ni > 0) - T = tframe - timestamps[ni-1]; + // Wait to load the next frame + ORB_SLAM2::Seconds T = 0.0; + if(ni < nImages-1) + T = timestamps[ni+1] - tframe; + else if(ni > 0) + T = tframe - timestamps[ni-1]; - if(ttrack < T) - usleep((T-ttrack) * 1e6); + if(ttrack < T) + usleep((T-ttrack) * 1e6); - } - - // Stop all threads - SLAM.Shutdown(); + } + + // Stop all threads + SLAM.Shutdown(); + + // Tracking time statistics + sort(vTimesTrack.begin(),vTimesTrack.end()); + ORB_SLAM2::Seconds totaltime = 0.0; + for(int ni = 0; ni < nImages; ni++) + { + totaltime+=vTimesTrack[ni]; + } + cout << "-------" << endl << endl; + cout << "median tracking time: " << vTimesTrack[nImages/2] << endl; + cout << "mean tracking time: " << totaltime/nImages << endl; - // Tracking time statistics - sort(vTimesTrack.begin(),vTimesTrack.end()); - ORB_SLAM2::Seconds totaltime = 0.0; - for(int ni = 0; ni < nImages; ni++) + // Save camera trajectory + string resultsPath_expId = exp_folder + "/" + paddingZeros(exp_id); + SLAM.SaveKeyFrameTrajectoryVSLAMLAB(resultsPath_expId + "_" + "KeyFrameTrajectory.csv"); + }; + + if(SLAM.ViewerRunsOnMainThread()) { - totaltime+=vTimesTrack[ni]; + std::thread trackingThread(processSequence); + SLAM.RunViewer(); + trackingThread.join(); + } + else + { + processSequence(); } - cout << "-------" << endl << endl; - cout << "median tracking time: " << vTimesTrack[nImages/2] << endl; - cout << "mean tracking time: " << totaltime/nImages << endl; - - // Save camera trajectory - string resultsPath_expId = exp_folder + "/" + paddingZeros(exp_id); - SLAM.SaveKeyFrameTrajectoryVSLAMLAB(resultsPath_expId + "_" + "KeyFrameTrajectory.csv"); return 0; } diff --git a/Examples/RGB-D/vslamlab_orbslam2_rgbd.cpp b/Examples/RGB-D/vslamlab_orbslam2_rgbd.cpp index e4e37581f8..66dc9ead4e 100644 --- a/Examples/RGB-D/vslamlab_orbslam2_rgbd.cpp +++ b/Examples/RGB-D/vslamlab_orbslam2_rgbd.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -126,52 +127,64 @@ int main(int argc, char **argv) cout << "Start processing sequence ..." << endl; cout << "Images in the sequence: " << nImages << endl << endl; - // Main loop - cv::Mat im, imD; - for(size_t ni = 0; ni < nImages; ni++) - { - // Read image from file - im = cv::imread(imageFilenames[ni],cv::IMREAD_UNCHANGED); - imD = cv::imread(depthFilenames[ni],cv::IMREAD_UNCHANGED); - ORB_SLAM2::Seconds tframe = timestamps[ni]; + auto processSequence = [&]() { + cv::Mat im, imD; + for(size_t ni = 0; ni < nImages; ni++) + { + // Read image from file + im = cv::imread(imageFilenames[ni],cv::IMREAD_UNCHANGED); + imD = cv::imread(depthFilenames[ni],cv::IMREAD_UNCHANGED); + ORB_SLAM2::Seconds tframe = timestamps[ni]; + + // Pass the image to the SLAM system + std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now(); + SLAM.TrackRGBD(im,imD,tframe); + std::chrono::steady_clock::time_point t2 = std::chrono::steady_clock::now(); + + ORB_SLAM2::Seconds ttrack = std::chrono::duration_cast >(t2 - t1).count(); + vTimesTrack[ni] = ttrack; + + // Wait to load the next frame + ORB_SLAM2::Seconds T = 0.0; + if(ni < nImages-1) + T = timestamps[ni+1] - tframe; + else if(ni > 0) + T = tframe - timestamps[ni-1]; + + if(ttrack < T) + usleep((T-ttrack) * 1e6); - // Pass the image to the SLAM system - std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now(); - SLAM.TrackRGBD(im,imD,tframe); - std::chrono::steady_clock::time_point t2 = std::chrono::steady_clock::now(); + } - ORB_SLAM2::Seconds ttrack = std::chrono::duration_cast >(t2 - t1).count(); - vTimesTrack[ni] = ttrack; + // Stop all threads + SLAM.Shutdown(); - // Wait to load the next frame - ORB_SLAM2::Seconds T = 0.0; - if(ni < nImages-1) - T = timestamps[ni+1] - tframe; - else if(ni > 0) - T = tframe - timestamps[ni-1]; + // Tracking time statistics + sort(vTimesTrack.begin(),vTimesTrack.end()); + ORB_SLAM2::Seconds totaltime = 0.0; + for(int ni = 0; ni < nImages; ni++) + { + totaltime+=vTimesTrack[ni]; + } + cout << "-------" << endl << endl; + cout << "median tracking time: " << vTimesTrack[nImages/2] << endl; + cout << "mean tracking time: " << totaltime/nImages << endl; - if(ttrack < T) - usleep((T-ttrack) * 1e6); + // Save camera trajectory + string resultsPath_expId = exp_folder + "/" + paddingZeros(exp_id); + SLAM.SaveKeyFrameTrajectoryVSLAMLAB(resultsPath_expId + "_" + "KeyFrameTrajectory.csv"); + }; + if(SLAM.ViewerRunsOnMainThread()) + { + std::thread trackingThread(processSequence); + SLAM.RunViewer(); + trackingThread.join(); } - - // Stop all threads - SLAM.Shutdown(); - - // Tracking time statistics - sort(vTimesTrack.begin(),vTimesTrack.end()); - ORB_SLAM2::Seconds totaltime = 0.0; - for(int ni = 0; ni < nImages; ni++) + else { - totaltime+=vTimesTrack[ni]; + processSequence(); } - cout << "-------" << endl << endl; - cout << "median tracking time: " << vTimesTrack[nImages/2] << endl; - cout << "mean tracking time: " << totaltime/nImages << endl; - - // Save camera trajectory - string resultsPath_expId = exp_folder + "/" + paddingZeros(exp_id); - SLAM.SaveKeyFrameTrajectoryVSLAMLAB(resultsPath_expId + "_" + "KeyFrameTrajectory.csv"); return 0; } diff --git a/Examples/Stereo/vslamlab_orbslam2_stereo.cpp b/Examples/Stereo/vslamlab_orbslam2_stereo.cpp index 769724960a..121463dc4d 100644 --- a/Examples/Stereo/vslamlab_orbslam2_stereo.cpp +++ b/Examples/Stereo/vslamlab_orbslam2_stereo.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -121,57 +122,69 @@ int main(int argc, char **argv) cout << "Start processing sequence ..." << endl; cout << "Images in the sequence: " << nImages << endl << endl; - // Main loop - cv::Mat imLeft, imRight, imLeftRect, imRightRect; - cv::Mat M1l, M2l, M1r, M2r; - SLAM.getStereoRectification(M1l, M2l, M1r, M2r); - for(size_t ni = 0; ni < nImages; ni++) - { - // Read image from file - imLeft = cv::imread(imageFilenames_l[ni], cv::IMREAD_UNCHANGED); - imRight = cv::imread(imageFilenames_r[ni], cv::IMREAD_UNCHANGED); - cv::remap(imLeft, imLeftRect, M1l, M2l, cv::INTER_LINEAR); - cv::remap(imRight, imRightRect, M1r, M2r, cv::INTER_LINEAR); - - ORB_SLAM2::Seconds tframe = timestamps[ni]; + auto processSequence = [&]() { + cv::Mat imLeft, imRight, imLeftRect, imRightRect; + cv::Mat M1l, M2l, M1r, M2r; + SLAM.getStereoRectification(M1l, M2l, M1r, M2r); + for(size_t ni = 0; ni < nImages; ni++) + { + // Read image from file + imLeft = cv::imread(imageFilenames_l[ni], cv::IMREAD_UNCHANGED); + imRight = cv::imread(imageFilenames_r[ni], cv::IMREAD_UNCHANGED); + cv::remap(imLeft, imLeftRect, M1l, M2l, cv::INTER_LINEAR); + cv::remap(imRight, imRightRect, M1r, M2r, cv::INTER_LINEAR); + + ORB_SLAM2::Seconds tframe = timestamps[ni]; + + // Pass the image to the SLAM system + std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now(); + SLAM.TrackStereo(imLeftRect,imRightRect,tframe); + std::chrono::steady_clock::time_point t2 = std::chrono::steady_clock::now(); + + ORB_SLAM2::Seconds ttrack = std::chrono::duration_cast >(t2 - t1).count(); + vTimesTrack[ni] = ttrack; + + // Wait to load the next frame + ORB_SLAM2::Seconds T = 0.0; + if(ni < nImages-1) + T = timestamps[ni+1] - tframe; + else if(ni > 0) + T = tframe - timestamps[ni-1]; + + if(ttrack < T) + usleep((T-ttrack) * 1e6); - // Pass the image to the SLAM system - std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now(); - SLAM.TrackStereo(imLeftRect,imRightRect,tframe); - std::chrono::steady_clock::time_point t2 = std::chrono::steady_clock::now(); + } - ORB_SLAM2::Seconds ttrack = std::chrono::duration_cast >(t2 - t1).count(); - vTimesTrack[ni] = ttrack; + // Stop all threads + SLAM.Shutdown(); - // Wait to load the next frame - ORB_SLAM2::Seconds T = 0.0; - if(ni < nImages-1) - T = timestamps[ni+1] - tframe; - else if(ni > 0) - T = tframe - timestamps[ni-1]; + // Tracking time statistics + sort(vTimesTrack.begin(),vTimesTrack.end()); + ORB_SLAM2::Seconds totaltime = 0.0; + for(int ni = 0; ni < nImages; ni++) + { + totaltime+=vTimesTrack[ni]; + } + cout << "-------" << endl << endl; + cout << "median tracking time: " << vTimesTrack[nImages/2] << endl; + cout << "mean tracking time: " << totaltime/nImages << endl; - if(ttrack < T) - usleep((T-ttrack) * 1e6); + // Save camera trajectory + string resultsPath_expId = exp_folder + "/" + paddingZeros(exp_id); + SLAM.SaveKeyFrameTrajectoryVSLAMLAB(resultsPath_expId + "_" + "KeyFrameTrajectory.csv"); + }; + if(SLAM.ViewerRunsOnMainThread()) + { + std::thread trackingThread(processSequence); + SLAM.RunViewer(); + trackingThread.join(); } - - // Stop all threads - SLAM.Shutdown(); - - // Tracking time statistics - sort(vTimesTrack.begin(),vTimesTrack.end()); - ORB_SLAM2::Seconds totaltime = 0.0; - for(int ni = 0; ni < nImages; ni++) + else { - totaltime+=vTimesTrack[ni]; + processSequence(); } - cout << "-------" << endl << endl; - cout << "median tracking time: " << vTimesTrack[nImages/2] << endl; - cout << "mean tracking time: " << totaltime/nImages << endl; - - // Save camera trajectory - string resultsPath_expId = exp_folder + "/" + paddingZeros(exp_id); - SLAM.SaveKeyFrameTrajectoryVSLAMLAB(resultsPath_expId + "_" + "KeyFrameTrajectory.csv"); return 0; } diff --git a/include/System.h b/include/System.h index 283b38e1ec..1fe53cd28c 100644 --- a/include/System.h +++ b/include/System.h @@ -96,6 +96,12 @@ class System // This function must be called before saving the trajectory. void Shutdown(); + // On macOS the Pangolin/Cocoa viewer must run on the main thread. + void RunViewer(); + + // Returns true when the caller should run RunViewer() on the main thread. + bool ViewerRunsOnMainThread() const; + // Save keyframe poses in the VSLAM-LAB dataset format. // This method works for all sensor input. // Call first Shutdown() diff --git a/src/System.cc b/src/System.cc index 36dd6d17b5..66acd3b750 100644 --- a/src/System.cc +++ b/src/System.cc @@ -32,6 +32,8 @@ namespace ORB_SLAM2 System::System(const string &strVocFile, const string &strCalibrationFile, const string &strSettingsFile, const eSensor sensor, const bool bUseViewer): mSensor(sensor), mpViewer(static_cast(NULL)), + mptLocalMapping(static_cast(NULL)), mptLoopClosing(static_cast(NULL)), + mptViewer(static_cast(NULL)), mbReset(false), mbActivateLocalizationMode(false), mbDeactivateLocalizationMode(false) { @@ -109,7 +111,11 @@ System::System(const string &strVocFile, const string &strCalibrationFile, const if(bUseViewer) { mpViewer = new Viewer(this, mpFrameDrawer,mpMapDrawer,mpTracker,strCalibrationFile,strSettingsFile,mSensor); +#ifdef __APPLE__ + // Cocoa/AppKit requires Pangolin's event loop to run on the process main thread. +#else mptViewer = new thread(&Viewer::Run, mpViewer); +#endif mpTracker->SetViewer(mpViewer); } @@ -326,10 +332,27 @@ void System::Shutdown() usleep(5000); } - if(mpViewer) + if(mpViewer && mptViewer) pangolin::BindToContext("ORB-SLAM2: Map Viewer"); } +void System::RunViewer() +{ +#ifdef __APPLE__ + if(mpViewer) + mpViewer->Run(); +#endif +} + +bool System::ViewerRunsOnMainThread() const +{ +#ifdef __APPLE__ + return mpViewer != NULL; +#else + return false; +#endif +} + void System::SaveKeyFrameTrajectoryVSLAMLAB(const string &filename) { cout << endl << "Saving keyframe trajectory to " << filename << " ..." << endl;