UZ-SLAMLab / ORB_SLAM3

ORB-SLAM3: An Accurate Open-Source Library for Visual, Visual-Inertial and Multi-Map SLAM
GNU General Public License v3.0
6.39k stars 2.51k forks source link

Load/Save Map #443

Open sumitsarkar1 opened 2 years ago

sumitsarkar1 commented 2 years ago

Thank you guys for the updated version ! On the GUI I could not figure out how to Save/Load a map. Do we have a separate flag for that or we need to use the GUI

dz306271098 commented 2 years ago

@sumitsarkar1 Please see Calibration_Tutorial.pdf in this project. It has introduced each parameter. And you can just Save/Load a map through some parameters.

sumitsarkar1 commented 2 years ago

@dz306271098 are you able to save the map? I applied the flag System.SaveAtlasToFile: "home/map" but I get segmentation fault

sumitsarkar1 commented 2 years ago

When the stop button is pressed Shutdown is printed twice but SLAM.Shutdown() is called once in stereo_inertial_realsense_t265.cc

dz306271098 commented 2 years ago

@sumitsarkar1 which dataset you test. I haven't met this situation when test in V101, MH01, MH05 EuRoC datasets.

sumitsarkar1 commented 2 years ago

I am testing with Intel Realsense T265

If you check the System::SaveAtlas(int type) neither of the cout gets printed for any of the if statements like if(type==TEST_FILE) or if(type==BINARY_FILE)

dz306271098 commented 2 years ago

@sumitsarkar1 I have checked. When you save map successfully, the cout gets printed. Like this 8BTVJTKTH$ZKU@%@TGCPTCV some of them are added by me. The end cout is from backward.cc which is used to show stack trace.

sumitsarkar1 commented 2 years ago

@dz306271098 let me know if you have any success for the seg fault

dz306271098 commented 2 years ago

@sumitsarkar1 ok~ But unfortunately, I don't have a reliable way, and usually meet this error, like this

start VIBA 1
end VIBA 1
start VIBA 2
end VIBA 2
Shutdown
start save map!!!!!!!!!11
Stack trace (most recent call last):
#10   Object "", at 0xffffffffffffffff, in 
#9    Object "/home/c2214-hs/Documents/test/ORB_SLAM3/Examples/Stereo-Inertial/stereo_inertial_euroc", at 0x55c83d209469, in _start
#8    Source "../csu/libc-start.c", line 310, in __libc_start_main [0x7f53fe5c5bf6]
#7    Object "/home/c2214-hs/Documents/test/ORB_SLAM3/Examples/Stereo-Inertial/stereo_inertial_euroc", at 0x55c83d208adc, in main
#6    Object "/home/c2214-hs/Documents/test/ORB_SLAM3/lib/libORB_SLAM3.so", at 0x7f5401244458, in ORB_SLAM3::System::Shutdown()
#5    Object "/home/c2214-hs/Documents/test/ORB_SLAM3/lib/libORB_SLAM3.so", at 0x7f5401243c96, in ORB_SLAM3::System::SaveAtlas(int)
#4    Object "/home/c2214-hs/Documents/test/ORB_SLAM3/lib/libORB_SLAM3.so", at 0x7f54012de274, in ORB_SLAM3::Atlas::PreSave()
#3    Object "/home/c2214-hs/Documents/test/ORB_SLAM3/lib/libORB_SLAM3.so", at 0x7f54012e0ffc, in ORB_SLAM3::Map::PreSave(std::set<ORB_SLAM3::GeometricCamera*, std::less<ORB_SLAM3::GeometricCamera*>, std::allocator<ORB_SLAM3::GeometricCamera*> >&)
#2    Object "/home/c2214-hs/Documents/test/ORB_SLAM3/lib/libORB_SLAM3.so", at 0x7f54012cad8e, in ORB_SLAM3::MapPoint::isBad()
#1    Object "/home/c2214-hs/Documents/test/ORB_SLAM3/lib/libORB_SLAM3.so", at 0x7f54012ce88c, in void std::lock<std::unique_lock<std::mutex>, std::unique_lock<std::mutex>>(std::unique_lock<std::mutex>&, std::unique_lock<std::mutex>&)
#0    Source "../nptl/pthread_mutex_lock.c", line 67, in __pthread_mutex_lock [0x7f53ff64efd0]
Segmentation fault (Signal sent by the kernel [(nil)])
Segmentation fault (core dumped)

I will continue to try.

knazneen123 commented 2 years ago

I have tried save load map feature and it works for euroc dataset MH_01 series, you need to change the .yaml file and add these params

--------------------------------------------------------------------------------------------

System config

--------------------------------------------------------------------------------------------

When the variables are commented, the system doesn't load a previous session or not store the current one

If the LoadFile doesn't exist, the system give a message and create a new Atlas from scratch

System.LoadAtlasFromFile: "mapeuro"

The store file is created from the current session, if a file with the same name exists it is deleted

System.SaveAtlasToFile: "mapeuro"

Above camera params By default it saves binary type for maps for this System::SaveAtlas(int type)

sumitsarkar1 commented 2 years ago

@knazneen123 already done those but I face seg fault for T265 and because of the fault may be I cant save the map

knazneen123 commented 2 years ago

I also faced this seg fault issue when the program terminates or while I try to shut it down using ctrl+c, it mainly happens due to some pointer being corrupted or null, you can try to check the functions called in saveAtlas() like presave or dont add .osa extension in the params they have already added it in the code, do verify the file name as well once it using to save. Also, do check the shutdown function of previous version and this in System.cc they have made some changes for viewer try removing those comments as well if in case later seg fault happens after saving function

dz306271098 commented 2 years ago

@sumitsarkar1 I think I have found the solution. There are maybe two unsuitable operations.

  1. void Map::PreSave(std::set<GeometricCamera*> &spCams) in Map.cc. When iterate mspMapPoints, mspMapPoints' size reduces. And I find void MapPoint::EraseObservation(KeyFrame* pKF) can change the 'mspMapPoints' during iteration. There may be other threads are working in the it, but I think the possibility is small.
  2. The similar situation also occur in void PreSave(set<KeyFrame*>& spKF,set<MapPoint*>& spMP) in MapPoint.cc. When iterate mObservations, the mObservations exists the possibility of change because of void MapPoint::EraseObservation(KeyFrame* pKF) during the iteration.

I have done some rough work on both of them, and it seems successful. Well, the above is just my guess, I can't guarantee that it will work. So it's just a reference.

sumitsarkar1 commented 2 years ago

@dz306271098 thnx for the suggestions...It will be helpful if you have a forked version of the recent ORBSLAM3 with the rough changes so that I can build that...

void System::SaveAtlas(int type){

    std::cout<< "INSIDE SAVE MAP" <<std::endl;
    if(!mStrSaveAtlasToFile.empty())
    {
        //clock_t start = clock();

        // Save the current session
        mpAtlas->PreSave();

Screenshot from 2021-12-29 13-21-55

This is with Realsense T265 . This seg fault is what I get

dz306271098 commented 2 years ago

@sumitsarkar1 I have updated the rough changes without using mutex in my forked version. And there are also some other problems. You can have a try. Maybe utilizing mutex is more reliable. I am fighting with my course examination recently (:з」∠)

Sherlock-hh commented 2 years ago

Hello, I have save and load the map successfully, but every time I loaded the map, the Tracker didn't use the saved map but create a new map, even though I turn the OnlyTracking-mode on, it's still tracking in the new map, am I use it in a wrong way? How could I use the loaded map to track? and I check the code I found

`bool isRead = LoadAtlas(FileType::BINARY_FILE);

        if(!isRead)
        {
            cout << "Error to load the file, please try with other session file or vocabulary file" << endl;
            exit(-1);
        }
        //mpKeyFrameDatabase = new KeyFrameDatabase(*mpVocabulary);

        //cout << "KF in DB: " << mpKeyFrameDatabase->mnNumKFs << "; words: " << mpKeyFrameDatabase->mnNumWords << endl;

        loadedAtlas = true;

        mpAtlas->CreateNewMap();`

and when the first frame came, StereoIntialization will set the first frame as the initial Frame and set it's pose to a identity matrix,how could relocalize in and turn the the Coordinate system to the loaded map

sumitsarkar1 commented 2 years ago

@Sherlock-hh on what are you able to save and load map successfully? Benchmark data sets or Sensors (Realsense)

Sherlock-hh commented 2 years ago

@Sherlock-hh on what are you able to save and load map successfully? Benchmark data sets or Sensors (Realsense)

realsense, stereo, sometimes it's failed to save map with different reasons, but most are accessing a null pointer, maybe it's because while presaving the map, loopclosing thread or localmapping thread are delete mappoint or keyFrame.

fengepsilon commented 2 years ago

delete mpMap->EraseMapPoint(this); in function void MapPoint::SetBadFlag()

JACKLiuDay commented 2 years ago

delete mpMap->EraseMapPoint(this); in function void MapPoint::SetBadFlag()

Hi guy, I tried your method ,while when I try to save map still got seg fault. image

Sherlock-hh commented 2 years ago

delete mpMap->EraseMapPoint(this); in function void MapPoint::SetBadFlag()

Hi guy, I tried your method ,while when I try to save map still got seg fault. image

Are u use imu+stereo mode? sorry, I didn't test it at imu+stereo.

JACKLiuDay commented 2 years ago

delete mpMap->EraseMapPoint(this); in function void MapPoint::SetBadFlag()

Hi guy, I tried your method ,while when I try to save map still got seg fault. image

Are u use imu+stereo mode? sorry, I didn't test it at imu+stereo.

Hi guy, I used it in mono+imu. And I am trying to read the code for digging out the reason.

image I believe this guy show the reason. But I do not know how to deal with it.

Sherlock-hh commented 2 years ago

yes, most of time it's caused by null pointer , you can add judge if it null when you prepare to save, or add mutex.

JACKLiuDay commented 2 years ago

yes, most of time it's caused by null pointer , you can add judge if it null when you prepare to save, or add mutex.

OK, thank you for your remind. I will try to find it. Maybe before saving the map, add some mutex to the map or map points will work.

JACKLiuDay commented 2 years ago

delete mpMap->EraseMapPoint(this); in function void MapPoint::SetBadFlag()

Hi guy, I tried your method ,while when I try to save map still got seg fault. image

After some test, I found the mpMap->EraseMapPoint(this) do have bugs when saving map. If we delete this function, there would be no error when saving a small map. When saving big map , about 100-200M, there still some errors after delete this function. It looks like the program stopped too quick while the map is still under saving. So some delay time should be added in the main function while loop. I still have some question. If we deleted the function mpMap->EraseMapPoint(this), the map we built would be bad quality or not?It seems like this function is running when the map is constructing. Or maybe we should implement this function in another form for avoiding the potential segmentation fault.

heiwang1997 commented 2 years ago

Applying the changes from this fork seems to solve my problem. Specifically, replace the Map::PreSave function and MapPoint::PreSave function with the following:

void Map::PreSave(std::set<GeometricCamera*> &spCams)
{
    int nMPWithoutObs = 0;

    std::set<MapPoint*> tmp_mspMapPoints1;
    tmp_mspMapPoints1.insert(mspMapPoints.begin(), mspMapPoints.end());

    for(MapPoint* pMPi : tmp_mspMapPoints1)
    {
        if(!pMPi || pMPi->isBad())
            continue;

        if(pMPi->GetObservations().size() == 0)
        {
            nMPWithoutObs++;
        }
        map<KeyFrame*, std::tuple<int,int>> mpObs = pMPi->GetObservations();
        for(map<KeyFrame*, std::tuple<int,int>>::iterator it= mpObs.begin(), end=mpObs.end(); it!=end; ++it)
        {
            if(it->first->GetMap() != this || it->first->isBad())
            {
                pMPi->EraseObservation(it->first);
            }

        }
    }

    // Saves the id of KF origins
    mvBackupKeyFrameOriginsId.clear();
    mvBackupKeyFrameOriginsId.reserve(mvpKeyFrameOrigins.size());
    for(int i = 0, numEl = mvpKeyFrameOrigins.size(); i < numEl; ++i)
    {
        mvBackupKeyFrameOriginsId.push_back(mvpKeyFrameOrigins[i]->mnId);
    }

    // Backup of MapPoints
    mvpBackupMapPoints.clear();

    std::set<MapPoint*> tmp_mspMapPoints2;
    tmp_mspMapPoints2.insert(mspMapPoints.begin(), mspMapPoints.end());

    for(MapPoint* pMPi : tmp_mspMapPoints2)
    {
        if(!pMPi || pMPi->isBad())
            continue;

        mvpBackupMapPoints.push_back(pMPi);
        pMPi->PreSave(mspKeyFrames,mspMapPoints);
    }

    // Backup of KeyFrames
    mvpBackupKeyFrames.clear();
    for(KeyFrame* pKFi : mspKeyFrames)
    {
        if(!pKFi || pKFi->isBad())
            continue;

        mvpBackupKeyFrames.push_back(pKFi);
        pKFi->PreSave(mspKeyFrames,mspMapPoints, spCams);
    }

    mnBackupKFinitialID = -1;
    if(mpKFinitial)
    {
        mnBackupKFinitialID = mpKFinitial->mnId;
    }

    mnBackupKFlowerID = -1;
    if(mpKFlowerID)
    {
        mnBackupKFlowerID = mpKFlowerID->mnId;
    }

}

and

void MapPoint::PreSave(set<KeyFrame*>& spKF,set<MapPoint*>& spMP)
{
    mBackupReplacedId = -1;
    if(mpReplaced && spMP.find(mpReplaced) != spMP.end())
        mBackupReplacedId = mpReplaced->mnId;

    mBackupObservationsId1.clear();
    mBackupObservationsId2.clear();
    // Save the id and position in each KF who view it
    std::map<KeyFrame*,std::tuple<int,int> > tmp_mObservations;
    tmp_mObservations.insert(mObservations.begin(), mObservations.end());

    for(std::map<KeyFrame*,std::tuple<int,int> >::const_iterator it = tmp_mObservations.begin(), end = tmp_mObservations.end(); it != end; ++it)
    {
        KeyFrame* pKFi = it->first;
        if(spKF.find(pKFi) != spKF.end())
        {
            mBackupObservationsId1[it->first->mnId] = get<0>(it->second);
            mBackupObservationsId2[it->first->mnId] = get<1>(it->second);
        }
        else
        {
            EraseObservation(pKFi);
        }
    }

    // Save the id of the reference KF
    if(spKF.find(mpRefKF) != spKF.end())
    {
        mBackupRefKFId = mpRefKF->mnId;
    }
}
tungtungyan commented 2 years ago

Hello, I have save and load the map successfully, but every time I loaded the map, the Tracker didn't use the saved map but create a new map, even though I turn the OnlyTracking-mode on, it's still tracking in the new map, am I use it in a wrong way? How could I use the loaded map to track? and I check the code I found

`bool isRead = LoadAtlas(FileType::BINARY_FILE);

        if(!isRead)
        {
            cout << "Error to load the file, please try with other session file or vocabulary file" << endl;
            exit(-1);
        }
        //mpKeyFrameDatabase = new KeyFrameDatabase(*mpVocabulary);

        //cout << "KF in DB: " << mpKeyFrameDatabase->mnNumKFs << "; words: " << mpKeyFrameDatabase->mnNumWords << endl;

        loadedAtlas = true;

        mpAtlas->CreateNewMap();`

and when the first frame came, StereoIntialization will set the first frame as the initial Frame and set it's pose to a identity matrix,how could relocalize in and turn the the Coordinate system to the loaded map

When I Load the bin File, it shows the problem of std::bad_alloc. How can I solve it? Initialization of Atlas from file: map_all Starting to read the save binary file: ./map_all.bin terminate called after throwing an instance of 'std::bad_alloc' what(): std::bad_alloc

I find that the problem is boost::archive::binary_iarchive ia(ifs);

Sherlock-hh commented 2 years ago

maybe the bin file is genarated before? Before u reloaded it,u changed some class Member variables, it's may causing the error. Or u didn't load the map file in the same order of saving, like u save it in order of atlas, map, and keyframedatebase, so when u load it like atlas, map, and keyframedatebase.

lygods commented 2 years ago

@tungtungyan I can save the map, but there is a segmentation error when loading the map

1656471989806

aganal commented 2 years ago

I met similar problem and tried all the method above, but it stil not work. Then I try to call System::Shutdown() manually, it works though i don't konw why ... here are the rough code: `

thread waitShut([&](){
    while (getchar()!='\n');
    flagShutdown = true;
});

while (!flagShutdown)
{
   ...
}

SLAM.Shutdown();
waitShut.join();

`

maalouf commented 2 years ago

Hello, saving the map works well (after very slight changes), however loading the map freezes the program, (pangolin freezes on startup and nothing works) no error is printed out. what do you recommend or suggest ?

827346462 commented 1 year ago

helle.I can load osa file . I ture Onlytracking modls . 2022-10-31 10-53-07屏幕截图

I change system.cc "mbActivateLocalizationMode(true)" to OnlyTracking. please you met?

build-error commented 6 months ago

A lot of people are having problems with saving and loading the map, I was too getting segmentation faults while saving/loading map.

I believe that the issue with string strVocabularyChecksum = CalculateCheckSum(mStrVocabularyFilePath,TEXT_FILE); . There may be some issue with CalculateCheckSum() function.

I ended up replacing this line with string strVocabularyChecksum = "someSampleText";. Make sure to change this line too string strInputVocabularyChecksum = "someSampleText";

These changes reduced the number of seg faults I was getting but, it didn't remove completely.

I also observed that when I was using Pangolin to see the GUI, while exiting I am seeing seg faults while the GUI is closing.

Running orbslam3 without GUI also reduced the number of seg faults.

doing all this hasn't removed all the seg faults i am facing but reduced it by a lot.