Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Load/Save Map #443

Open
sumitsarkar1 opened this issue Dec 25, 2021 · 32 comments
Open

Load/Save Map #443

sumitsarkar1 opened this issue Dec 25, 2021 · 32 comments

Comments

@sumitsarkar1
Copy link

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
Copy link

@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
Copy link
Author

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

@sumitsarkar1
Copy link
Author

sumitsarkar1 commented Dec 27, 2021

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

@sumitsarkar1 sumitsarkar1 reopened this Dec 27, 2021
@dz306271098
Copy link

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

@sumitsarkar1
Copy link
Author

sumitsarkar1 commented Dec 27, 2021

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
Copy link

dz306271098 commented Dec 27, 2021

@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
Copy link
Author

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

@dz306271098
Copy link

@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
Copy link

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
Copy link
Author

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

@knazneen123
Copy link

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
Copy link

dz306271098 commented Dec 29, 2021

@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
Copy link
Author

sumitsarkar1 commented Dec 29, 2021

@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
Copy link

@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
Copy link

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
Copy link
Author

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

@Sherlock-hh
Copy link

@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
Copy link

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

@JACKLiuDay
Copy link

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
Copy link

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
Copy link

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
Copy link

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
Copy link

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
Copy link

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
Copy link

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
Copy link

tungtungyan commented Jun 14, 2022

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
Copy link

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
Copy link

lygods commented Jun 29, 2022

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

1656471989806

@aganal
Copy link

aganal commented Jul 27, 2022

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
Copy link

maalouf commented Jul 28, 2022

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
Copy link

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
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests