-
Notifications
You must be signed in to change notification settings - Fork 118
Integrate custom SLAM
OpenREALM is designed in such way, that it takes minimal effort (hopefully) to implement custom SLAM approaches. There are basically X important steps, that are described in the following.
Make it build, install and searchable
The easiest way to integrate your custom SLAM is to build and install it system-wide so CMake is able to find it. To do so, you need to provide package support. This is not my business though, so please refer to the CMake docs: https://cmake.org/cmake/help/latest/manual/cmake-packages.7.html
Make OpenREALM find and link it
After making sure you installed your SLAM correctly and CMake is able to find it, you can take the next step. Now we let OpenREALM know what you are up to. This is one of the more complicated steps, so follow it thoroughly.
Right now OpenREALM should only be built with one SLAM framework at a time. This is to prevent errors due to different frameworks using the same shared library but different versions of it (G2O is a typical candidate for this). So our first step is letting CMake know we don't want any of the other potential candidates be built, but our own custom one.
Go to modules/realm_vslam/realm_vslam_base/CMakeLists.txt
and do the following:
- Give your custom SLAM a name. This is only used within this CMakeLists file, so it is rather unimportant how exactly you call it. However, make it unique.
set(VSLAM_IMPL_TYPE "CUSTOM_SLAM")
- Add library, headers and build flag as well as your future interface class
elseif(VSLAM_IMPL_TYPE STREQUAL "CUSTOM_SLAM")
set(VSLAM_IMPL_LIB CustomSLAM)
set(VSLAM_IMPL_LIB_HEADERS ${CustomSLAM_INCLUDE_DIR})
set(VSLAM_IF_HEADERS ${root}/include/realm_vslam_base/custom_slam.h)
set(VSLAM_IF_SOURCES ${root}/src/custom_slam.cpp)
set(VSLAM_IF_COMPILE_FLAG "-DUSE_CUSTOM_SLAM=ON")
message(STATUS "Selected Custom SLAM for visual pose estimation")
This is one of the crucial steps. So let's understand it line by line:
#1: First we add a definition that is going to be passed into our code so we can instantiate the custom SLAM inside OpenREALM
#2: We set the library name of our custom SLAM. This must be identical to the definition in the CMake config. So basically further down the line we will call find_package(VSLAM_IMPL_LIB), so make sure the name is correct!
#3: At best the headers are found in your cmake target.
#4: This is a first foreshadowing of what's coming. Very soon we will need to implement an interface class, so OpenREALM knows how to pass data to your custom SLAM.
#5: Same as #5 just the source file for your future interface.
#6: Here we check if custom slam was really selected in the beginning (at set(VSLAM_IMPL_TYPE ...)).
#7: Let people know it worked selecting your custom SLAM during configuration phase. It can save trouble, trust me.
Provide an interface class on how your SLAM works
Well done my Padawan. If you did everything right OpenREALM will now be able to find your framework and link against it. However, it is not yet the right time to test it. It would escalate in build errors, because OpenREALM expects to find some interface class that you already named, but won't find any. So here is what to do next.
- Create an interface class
Create the interface class which you named prior in line #5 and #6. So likely something like custom_slam.h
and custom_slam.cpp
and put it into the realm_vslam_base folder. Here is a minimal example:
Not that these are just the absolute bare minimum functions to implement. Have a look into visual_slam_IF.h for other virtual functions to implement. Your SLAM should follow this basic workflow, if it doesn't, you are going to have a very hard time to integrate it. But if you ask me, this should be generic enough, isn't it?
You can either directly implement these functions, or let just create empty functions. I'd recommend the latter, so we can first check if your package is correctly found and integrated into OpenREALM before you implement the details on how to use your framework.
Provide a custom settings file
Ah, you thought you can start already, didn't you? I have to disappoint you. It is not quite ready for a build call. Because OpenREALM is reading all its settings from yaml files, it is convenient to use this for your custom SLAM as well. But you don't have to put too much thought into it right now, we can also leave it empty until we really want to use it.
Go to modules/realm_vslam/realm_vslam_base/visual_slam_settings.h
and add a settings config for your custom slam. There are several examples in that file already, some of them are not really used anymore but can offer you a nice 'How to'. The minimal working example should look something like this:
Add your settings to the visual SLAM settings factory
It is good OpenREALM knows now about the settings you might provide. But it doesn't know what settings class to create from your yaml in the first place. To achieve this add the following lines:
// in visual_slam_settings_factory.cpp
if (method == "CUSTOM_SLAM")
return loadDefault<CustomSlamSettings>(filepath, directory);
Add your interface into the visual SLAM factory
It's not too many steps anymore, I promise. Next is to add your custom interface into the visual SLAM factory, so OpenREALM creates it properly. To understand the lines, one has to know that OpenREALM must be provided with a settings file for the visual SLAM to be used. This settings file has a line stating what 'type' it is, so basically the name of the framework. It will read 'type' and compare it to the string he finds in the factory. If it exists, he will happily create an instance of your custom SLAM. To achieve this for your custom SLAM this is necessary:
// in visual_slam_factory.h
elif USE_CUSTOM_SLAM
#include <realm_vslam_base/custom_slam.h>
// in visual_slam_factory.cpp
#elif USE_OPEN_VSLAM
if ((*vslam_set)["type"].toString() == "CUSTOM_VSLAM")
return std::make_shared<CustomSlam>(vslam_set, cam_set);
Note that the hash defines must be identical to the ${VSLAM_IF_COMPILE_FLAG} you put in the CMakeLists.txt earlier!
Note also, that the string comparison must be equal to the 'type' you provide in the custom_slam_settings.yaml!
Now you are ready to compile OpenREALM with your custom SLAM framework for the first time. If you did everything right it should successfully build with the standard procedures given in the readme.
Create a settings file and load it
Up to this point we haven't filled the functions of your interface. This is quite an individual task, but you can find an example in the orb_slam.cpp
file. Basically all you have to do is instantiate your framework and define how to feed the data into it. One last important step on OpenREALM side has to be done though.
If you have a look at our ROS1 bridge: https://github.com/laxnpander/OpenREALM_ROS1_Bridge you will see that we work with "profiles", which is more or less a fancy word for a collection of settings. In the roslaunch file you will also see, that these profiles are loaded at start. Within the profile there is also a hint on what visual SLAM framework should be used. For your custom slam such a settings file does not yet exist. Go to OpenREALM_ROS1_Bridge/realm_ros/profiles/your_profile/pose_estimation/method
and create a new file named custom_slam_settings.yaml
. This file should contain the same settings that you added earlier in the visual_slam_settings.h
. We left it empty, so you don't have to add much. However, two parameters are required:
- type: CUSTOM_SLAM -> You remember the line you added in the visual slam factory? It was comparing a string "type" to different options and then instantiates the SLAM framework based on that information. This here must exactly match the string that is compared to in
visual_slam_factory.cpp
. - resizing: 1.0 -> This is also a parameter that is always read. It sets the factor the image dimensions (width, height) are multiplied with. The smaller the number, the smaller the image the SLAM is working with. Ideally you go with the full resolution (1.0), but sometimes on lower resource machines it might be necessary to make it 0.5 or less.
Run it
If you use our ROS1 bridge, the last step really is to add the framework you want to use to the roslaunch file. It is basically just a sanity check that you know what framework you compiled with and that it uses your exact choice. Here the respective part of the roslaunch file. The interesting part is the "config/method". The name provided here must match the name you gave your settings file like {name}_settings.yaml
<node pkg="realm_ros" type="realm_stage_node" name="realm_pose_estimation" output="screen">
<param name="stage/type" type="string" value="pose_estimation"/>
<param name="stage/master" type="bool" value="true"/>
<param name="topics/input" type="string" value="$(arg topic_adapter)"/>
<param name="topics/output" type="string" value="$(arg topic_pose_est)"/>
<param name="config/id" type="string" value="$(arg camera_id)"/>
<param name="config/profile" type="string" value="alexa_reco"/>
<param name="config/method" type="string" value="custom_slam"/>
</node>
That's it, you are ready to go for a run!