FDML is a software for robot localization processing and queries using few (one or two) distance measurements, written in C++.
Imagine the following situation. A robot is placed in an unknown position and unknown orientation in a known polygon (with holes) environment. The robot has a depth sensor, that is a sensor that can measure the scalar length of a ray from it's position to a wall in a specific direction. The depth sensor is used to measure a single distance measurement with the robot unknown position and orientation, where does the robot can be within the environment given the new information? Same question can be asked when the robot is allowed to make a second distance measurement.
The FDML library support these types of queries. For two distance measurements, the library support two antipodal (180 °) measurements, in other words, the robot measure a distance measurement in some orientation, then rotate in place to the exact opposite direction and measure a second distance measurement. A polygon environment can be preprocessed and support multiple queries efficiently.
The library is written in C++, but bindings exists for Python, and an additional GUI application.
The FDML-core is the C++ heart of the library and contains all the logic. It can be used as a C++ library, from Python using the bindings, or using command line application (basic CLI, daemon with communication through files). It's built on top of CGAL, which depends on boost, gmp and mpfr.
The library interface is done via Locator object which support three functions:
class Locator {
Locator();
void init(const Polygon_with_holes& scene);
std::vector<Res1d> query(const Kernel::FT& d) const;
std::vector<Res2d> query(const Kernel::FT& d1, const Kernel::FT& d2) const;
}void init(scene)Perform preprocessing on the given polygon scenevector<Res> query(d)Calculates all the positions in the scene a sensor might be, given the information it performed a single distance measurement with a value ofd.vector<Res> query(d1, d2)Calculates all the positions in the scene a sensor might be, given the information it performed two distance measurements with a values ofd1,d2.
A simple square scene example:
Polygon_with_holes scene;
scene.push_back(Point(0, 0));
scene.push_back(Point(0, 10));
scene.push_back(Point(10, 10));
scene.push_back(Point(10, 0));
/* locator is initiated with a polygon scene */
Locator locator;
locator.init(scene);
/* Assuming a robot is within the given scene, in an unknown location and an
* unknown orientation, after performing a single distance measurement, the
* locator can be used to calculate all the possible location the robot
* might be in.
* Queries of a single measurement result in a collection of areas representing
* all the possible locations of the robot, each represented as polygon and the
* measured edge.
*/
double robot_measurement = 5.7;
std::vector<Res1d> single_res = locator.query(robot_measurement);
std::count << "Single measurement possible positions:" << std::endl;
for (const auto& res_area : single_res)
std::count << "\tPossible positions of measuring edge (" << res_area.edge << "): " << res_area.pos << std::endl;
/* If the robot is able to perform a second distance measurement in the
* opposite direction of the first measurement, the locator can be used to
* calculate a more accurate localization result using the two measurements.
* Queries of double measurements result in a collection of segments
* representing all the possible locations of the robot.
*/
double second_robot_measurement = 2.4;
std::vector<Res2d> double_res = locator.query(robot_measurement, second_robot_measurement);
std::count << "Double measurements possible positions:" << std::endl;
for (const auto& res_area : double_res)
std::count << "\tPossible positions of measuring edges (" << res_area.edge1 << "),(" << res_area.edge2
<< "): " << res_area.pos << std::endl;The dependencies of the library are Boost, GMP, MPFR and CGAL. If Python bindings are built, also nanobind is required.
In this guide we will clone the FDML repo into C:\fdml\, install the dependencies into C:\fdml_deps\ and build FDML atrifacts into C:\fdml_build\. You should change these paths according to your needs.
-
Install
cmakeandMSVC -
Install
GMPandMPFR: Download and unzip the binaries from this link intoC:\fdml_deps\gmp_mpfr, and setGMPandMPFRenvironment variables:$env:GMP_DIR="C:\fdml_deps\gmp_mpfr" $env:MPFR_DIR="C:\fdml_deps\gmp_mpfr" -
Install
boostvia installer intoC:\fdml_deps\boost_1_82_0and set its environment variables (replace1_82_0and14.3if you are using different versions):$env:BOOST_INCLUDEDIR="C:\fdml_deps\boost_1_82_0" $env:BOOST_LIBRARYDIR="C:\fdml_deps\boost_1_82_0\lib64-msvc-14.3" -
Install
CGALand set its environment variables:git clone https://github.com/CGAL/cgal.git C:\fdml_deps\cgal mkdir C:\fdml_deps\cgal\build cd C:\fdml_deps\cgal\build cmake -A x64 .. $env:CGAL_DIR="C:\fdml_deps\cgal\build" -
Clone the
FDMLrepository:git clone https://github.com/barakugav/FDML.git C:\fdml -
Build using
cmake:mkdir C:\fdml_build\ cd C:\fdml_build\ cmake -A x64 -DBUILD_SHARED_LIBS:BOOL=ON -DCMAKE_BUILD_TYPE=Release -DFDML_WITH_PYBINDINGS:BOOL=OFF C:\fdml\ cmake --build . -j
The installation follow the same steps as above, with addition dependencies installation before building via cmake:
-
Install
nanobindgit clone https://github.com/wjakob/nanobind.git C:\fdml_deps\nanobind cd C:\fdml_deps\nanobind git submodule update --init $env:nanobind_DIR="C:\fdml_deps\nanobind\" -
install
Pythondependenciespip install -r C:\fdml\fdmlpy\requirements.txt
When running cmake, pass -DFDML_WITH_PYBINDINGS:BOOL=ON, and than build normally via cmake --build ..
In this guide we will clone the FDML repo into ~/fdml/, install the dependencies into ~/fdml_deps/ and build FDML atrifacts into ~/fdml_build/. You should change these paths according to your needs.
-
Install
C++build tools:sudo apt-get install build-essential checkinstall m4 g++ cmake
-
Install
GMPandMPFR:sudo apt-get install libgmp3-dev sudo apt-get install libmpfr-dev libmpfr-doc
-
Install
boost: Unfortenetly, theboostversion installed throughapt-getis currently1.71.0and we require version1.75.0and above. Therefore, we need to download and buildboostmanually:cd ~/fdml_deps/ wget -O boost_1_79_0.tar.gz https://sourceforge.net/projects/boost/files/boost/1.79.0/boost_1_79_0.tar.gz/download tar xzf boost_1_79_0.tar.gz rm boost_1_79_0.tar.gz cd boost_1_79_0 ./bootstrap.sh ./b2 --build-dir=./build --stagedir=./bin architecture=x86 address-model=64 link=static,shared --variant=debug,release --without-python export BOOST_INCLUDEDIR="~/fdml_deps/boost_1_79_0" export BOOST_LIBRARYDIR="~/fdml_deps/boost_1_79_0/bin/lib" -
Install
CGALand set its environment variables:git clone https://github.com/CGAL/cgal.git ~/fdml_deps/cgal mkdir ~/fdml_deps/cgal/build cd ~/fdml_deps/cgal/build cmake .. export CGAL_DIR="~/fdml_deps/cgal/build" -
Clone the
FDMLrepository:git clone https://github.com/barakugav/FDML.git ~/fdml -
Build using
cmakeandmake:mkdir ~/fdml_build/ cd ~/fdml_build/ cmake -DBUILD_SHARED_LIBS:BOOL=ON -DCMAKE_BUILD_TYPE=Release -DFDML_WITH_PYBINDINGS:BOOL=OFF ~/fdml/ make -j
The installation follow the same steps as above, with addition dependencies installation before the the building using cmake:
-
Install
nanobindgit clone https://github.com/wjakob/nanobind.git ~/fdml_deps/nanobind cd ~/fdml_deps/nanobind git submodule update --init export nanobind_DIR="~/fdml_deps/nanobind/" -
install
Pythondependenciespip install -r ~/fdml/fdmlpy/requirements.txt
When running cmake, pass -DFDML_WITH_PYBINDINGS:BOOL=ON, and than build normally via make -j.
FDML-core is required, see FDML-core section. In the future, FDML-py, the Python bindings, will be required as well.
Install python dependencies:
pip install -r ./fdml-gui/requirements.txt
TODO
python fdml-gui/fdmlgui/scene_designer.py
python fdml-gui/fdmlgui/locator_gui.py