for Robotics Applications

When it comes to Machine Learning, Tensorflow is an ubiquitous tool that simplifies your entire workflow, allowing anyone to build and train a basic model in mere minutes. Developed primarily to be integrated in Python, it couples complex functions and operations with the convenience that Python offers.
However, we all know that convenience comes at the cost of performance. Statically-typed languages like C++ or Java check that variable types are unchanged at compile-time, which saves on any runtime checks. On the other hand, Python is a dynamically-typed language, which means that you can change variables and methods at runtime. This introduces runtime checks to minimise any errors, which is why most people familiar with statically-typed languages often complain that Python is slow.
![Time Comparison of C++ and Python with sorting algorithms [1].](https://towardsdatascience.com/wp-content/uploads/2021/10/1aM2du75z1lnYj4AatbwUYA.png)
Indeed, with the large number of variables and functions that make up a fairly sizeable machine learning model, Python‘s sluggishness can be detrimental for both training and inference. Though the difference in speed is hardly noticeable for general purposes, it does play a part in certain uses cases, such as Collaborative Simultaneous Localisation and Mapping (CSLAM) for robots.
In brief terms, CSLAM aims to utilise a team of robots to efficiently explore an unknown environment, all while determining their precise location at any point in time, and also generating an accurate depiction of their environment in the form of a map. Read more on CSLAM here.
![Visualisation of CSLAM [2].](https://towardsdatascience.com/wp-content/uploads/2021/10/11uW8PYMDdBTUafnj6-kGTw.png)
For robots to execute CSLAM, they need to go through a series of stages, which include utilising deep learning models for feature detection and place recognition. This helps them become more aware of their surroundings and provide higher confidence on their exact locations. As robots are constantly on the move and collecting data, it is crucial that CSLAM runs in real-time so that progress is not hindered. Hence, the widely-used Robot Operating System (ROS) code is often written in C++ to favour performance. As such, it will also boost speeds to run inference for deep learning models using the TensorFlow C++ API.
State-of-the-art deep learning models developed by top researchers tend to use the older Tensorflow 1.x instead of the more robust 2.x (ironic, I know). Installing 2.x from source is quite straightforward, but 1.x has next to no instructions with some broken links. Hence, I intend to address these issues by writing a one-step script.
Prerequisites
The script assumes a default distro, Ubuntu 18.04, and versions of dependencies such as GCC depend on the distro you are using. Feel free to modify the script based on your OS.
CUDA is also highly recommended (but not necessary). Instructions for installing the latest version can be found here.
The first step is to install libraries that we need to run future commands:
sudo apt-get update
sudo apt-get install -y build-essential curl git cmake unzip autoconf autogen automake libtool mlocate zlib1g-dev gcc-7 g++-7 wget
sudo apt-get install -y python python3 python3-numpy python3-dev python3-pip python3-wheel
sudo apt-get install -y python3.6 python3.6-dev
sudo updatedb
# Set GCC-7 as default
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 100
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-7 100
Building Tensorflow From Source
We employ a build tool, Bazel, to install Tensorflow. This script is based on a single version of Tensorflow, specifically Tensorflow 1.14.0. If you intend to install any other version, do be aware that the version of Bazel will also need to be updated. For a complete list of versions of Tensorflow and its dependencies, check out this link.
The following script checks for the existing version of Bazel and updates to the specified version:
###--- BAZEL 0.24.1 ---###
BAZEL_VER=`bazel version | grep "Build label" | awk '{print $3}'`
if [[ $BAZEL_VER != "0.24.1" ]]; then
if [ ! -f bazel-0.24.1-installer-linux-x86_64.sh ]; then
wget https://github.com/bazelbuild/bazel/releases/download/0.24.1/bazel-0.24.1-installer-linux-x86_64.sh
fi
chmod u+x bazel-0.24.1-installer-linux-x86_64.sh
./bazel-0.24.1-installer-linux-x86_64.sh
fi
bazel version
Next is to clone the Tensorflow GitHub repo:
###--- TF 1.14.0 ---###
if [ ! -d tensorflow ]; then
git clone https://github.com/tensorflow/tensorflow.git
fi
cd tensorflow
git checkout v1.14.0
If you try to run the build script, you will most likely run into a bunch of errors, one of which includes being unable to download Eigen. This is because the mirror links in the original build script are broken, so we need to find an alternative mirror.
echo "Replacing broken Eigen URLs..."
find . -type f -exec sed -i 's/http.*bitbucket.org/eigen/eigen/get/https://storage.googleapis.com/mirror.tensorflow.org/bitbucket.org/eigen/eigen/get/g' {} ;
EIGEN_COUNT=`grep -nr "https://storage.googleapis.com/mirror.tensorflow.org/bitbucket.org/eigen/eigen/get/" | wc -l`
if [ $EIGEN_COUNT -ne 6 ]; then
echo "Eigen URLs not updated!"
echo "Please manually replace all occurrences of"
echo "http.*bitbucket.org/eigen/eigen/get"
echo "with"
echo "https://storage.googleapis.com/mirror.tensorflow.org/bitbucket.org/eigen/eigen/get"
exit 1
fi
Then, we can download the external libraries required by Tensorflow by running the script:
chmod u+x tensorflow/contrib/makefile/download_dependencies.sh
./tensorflow/contrib/makefile/download_dependencies.sh
The last pre-processing step is to install Protobuf headers to your /usr/local/
directory:
###--- PROTOBUF 3.7.1 ---###
cd tensorflow/contrib/makefile/downloads/protobuf
git submodule update --init --recursive
./autogen.sh
./configure
make -j$(nproc)
make check -j$(nproc)
sudo make install
sudo ldconfig
Finally, we can start compiling Tensorflow! In the main Tensorflow directory, run the following:
# Configures dependencies versions and what is going to be built
# Customise to your own needs
./configure
bazel build --config=opt //tensorflow:libtensorflow_cc.so //tensorflow:install_headers
This step can take up to an hour depending on how many threads your CPU can run, so get a cup of coffee or go for a nice jog to clear your mind from all the scripting!
Installing Headers
If the build finished without any errors, it means you have been successful! All that’s left to do is to install the relevant headers to your /usr/local/
directory so that you can call them from wherever your project may be:
sudo mkdir /usr/local/tensorflow
sudo cp -r bazel-genfiles/tensorflow/include/ /usr/local/tensorflow/
sudo cp -r /usr/local/include/google/ /usr/local/tensorflow/include/
sudo mkdir /usr/local/tensorflow/lib
sudo cp -r bazel-bin/tensorflow/* /usr/local/tensorflow/lib
Testing
If you would like to double check that you can include headers without any issues, try running the Hello World equivalent in Tensorflow:
The full script can be found here. All you need to do is to run this script and it will execute all the aforementioned steps, and even perform some auto-configurations. If you do spot any bugs, please submit an issue or a pull request and let me know!
If you would like to share any ideas or opinions, do leave a comment below, or drop me a connect on LinkedIn.
References
[1] F. Zehra, M. Javed, D. Khan, M. Pasha, Comparative Analysis of C++ and Python in Terms of Memory and Time (2020), Preprints 2020, 2020120516 (doi: 10.20944/preprints202012.0516.v1).
[2] R. Dubé, A. Gawel, H. Sommer, J. Nieto, R. Siegwart, C. Cadena, An Online Multi-Robot SLAM System for 3D LiDARs (2017), IEEE/RSJ International Conference on Intelligent Robots and Systems (IROS).