# Preparing a multi-session map: map anchoring, loop-closure, pose-graph relaxation¶

This tutorial will guide you through the process of merging different maps of the same environment together. As an example use case, we will merge the maps generated from the Euroc machine hall 1, 2 and 3 datasets. You can download the unoptimized VI maps from the [[Sample Datasets]] page. Then, optionally, to improve the results, optimize and loop-close each of these maps individually and save the map again.

## Merging together different maps¶

Start a maplab console:

roscore&
rosrun maplab_console maplab_console


If there are no maps loaded into the console, you can use the following command to merge different VI maps from the file system directly together:

load_merge_all_maps --maps_folder path/to/optimized/euroc_maps


This creates a map in the console that is the product of merging all maps within path/to/optimized/euroc_maps together. You can then confirm that there is a mission for each in the individual maps by typing ms:

maplab <euroc_maps>:/$ms I1102 13:44:08.304085 7219 vi-map-basic-plugin.cc:973] VI-Map: Mission 0: e4a9a7f9ffffffff0e00000000000000 Viwls Vertices: 3677 Landmarks: 132954 Landmarks by first observer backlink: Camera 0: 132954 (g:31097 b:101857 u:0) Observations: 2319656 Num edges by type: IMU: 3676 Wheel-odometry: 0 Loop-closure: 0 Distance travelled [m]: 84.611516 Start to end time: 2017_11_02_13_44_08 to 2017_11_02_13_44_08 T_G_M unknown Num GPS measurements: 0/0 (UTM/WGS) Mission 1: 0cfe1a24000000000e00000000000000 Viwls Vertices: 3036 Landmarks: 116748 Landmarks by first observer backlink: Camera 0: 116748 (g:28581 b:88167 u:0) Observations: 1883207 Num edges by type: IMU: 3035 Wheel-odometry: 0 Loop-closure: 0 Distance travelled [m]: 78.673416 Start to end time: 2017_11_02_13_44_08 to 2017_11_02_13_44_08 T_G_M unknown Num GPS measurements: 0/0 (UTM/WGS) Mission 2: ec0479dfffffffff0e00000000000000 Viwls Vertices: 2695 Landmarks: 95580 Landmarks by first observer backlink: Camera 0: 95580 (g:29244 b:66336 u:0) Observations: 1467939 Num edges by type: IMU: 2694 Wheel-odometry: 0 Loop-closure: 0 Distance travelled [m]: 134.781190 Start to end time: 2017_11_02_13_44_08 to 2017_11_02_13_44_08 T_G_M unknown Num GPS measurements: 0/0 (UTM/WGS)  Visualizing the map gives the following result: spatially_distribute_missions v --vis_color_by_mission  ## Alternative ways to merge maps¶ This section briefly lists alternative ways to merge multiple maps. ### join_all_maps¶ load_all --maps_folder path/to/optimized/euroc_maps join_all_maps --target_map_key euroc_maps  join_all_maps merges all loaded maps together into a map given by target_map_key. ### load_merge¶ load --map_folder path/to/optimized/euroc_maps/MH_01_easy_optimized/ load_merge_map --map_folder path/to/optimized/euroc_maps/MH_02_easy_optimized/ load_merge_map --map_folder path/to/optimized/euroc_maps/MH_03_medium_optimized/  load_merge_map loads the map under the path given by map_folder and merges it with the selected map. ### merge_map¶ load --map_folder path/to/optimized/euroc_maps/MH_01_easy_optimized/ load --map_folder path/to/optimized/euroc_maps/MH_02_easy_optimized/ load --map_folder path/to/optimized/euroc_maps/MH_03_medium_optimized/ merge_map --map_key MH_01_easy_optimized merge_map --map_key MH_02_easy_optimized  merge_map merges the map given by map_key into the selected map. ## Mission anchoring¶ Each mission defines a baseframe transformation T_G_M. Initially, this transformation is unknown as we don’t have any information about where the missions should be anchored and what are the transformations between them. The map statistics command ms shows this information: Mission 0: e4a9a7f9ffffffff0e00000000000000 Viwls ... T_G_M unknown Mission 1: 0cfe1a24000000000e00000000000000 Viwls ... T_G_M unknown Mission 2: ec0479dfffffffff0e00000000000000 Viwls ... T_G_M unknown  In the process of mission anchoring, this T_G_M will be estimated. This is done by finding loop closures between a mission with an unknown baseframe and the missions with known baseframes. At least one of the missions needs to be known. We therefore mark an arbitrary mission of the dataset as known: sbk  sbk (short for set mission baseframe to known) operates on the first mission by default and sets its baseframe to known. This changes the output of ms to the following: Mission 0: e4a9a7f9ffffffff0e00000000000000 Viwls ... T_G_M unknown Mission 1: 0cfe1a24000000000e00000000000000 Viwls ... T_G_M known Mission 2: ec0479dfffffffff0e00000000000000 Viwls ... T_G_M unknown  Now we can anchor the other missionsn: aam  This command (short for anchor all missions) will try to estimate all the unknown baseframe transformation. The output of ms should look like this now: Mission 0: e4a9a7f9ffffffff0e00000000000000 Viwls ... T_G_M known Mission 1: 0cfe1a24000000000e00000000000000 Viwls ... T_G_M known Mission 2: ec0479dfffffffff0e00000000000000 Viwls ... T_G_M known  Additionally, the command print_baseframes will also provide the values of the estimated transformations: maplab <euroc_maps>:/$ print_baseframes
I1102 14:04:32.419026 10394 vi-map-basic-plugin.cc:1031] Baseframe transformations:
Mission 0 (e4a9a7f9ffffffff0e00000000000000):
status: known
T_G_M:
0.999388  0.0349801          0   0.250711
-0.0349801   0.999388         -0   0.710199
-0          0          1   0.558163
0          0          0          1

Mission 1 (0cfe1a24000000000e00000000000000):
status: known
T_G_M:
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1

Mission 2 (ec0479dfffffffff0e00000000000000):
status: known
T_G_M:
0.999838  -0.0179926           0 -0.00545835
0.0179926    0.999838           0    0.349317
0           0           1   0.0958929
0           0           0           1


The resulting map will look like this:

## Posegraph relaxation¶

Once the missions are anchored in a single coordinate frame, it is worth to relax the map using robust posegraph relaxation. This algorithm looks for matching keyframes between pairs of missions, creates relative 6DoF edges and performs an optimization operating on the odometry and loopclosure edges. The output of the relaxation is a globally consistent map that is a perfect starting point for further refinement (e.g. using visual-inertial least squares).

# Pose graph relaxation to close large loops.
relax


## Optimization and loop closure¶

Optimization and loop closure can be done like in the single-mission case. Keyframing (kfh) reduces the number of vertices/landmarks (so complexity of the optimization) and loopclosure (lc) merges the landmarks and creates visual constraints between missions. Finally, optvi performs a batch visual-inertial least squares optimization to refine the map geometry.

# (Optional) Key-frame the map.
kfh
# Loop close the map.
lc