This note has been updated in July 2022.

Achieving Real-Time capability with Linux

In robotics, we need computer programs are real-time to control robotics and devices. These program listen to signals from sensors, cameras; compute stuffs; and then send motion commands to the robot controller. Everything happen quickly and in real-time.

graph LR A[Sensor] -->|measures| B(Sensor Data) B --> C{Process: thinking ...} C -->|Send data| D[Robot]

In addition to the usual logical/business requirements, we need to consider real-time requirements for these classes of problems.

In a common Operating System (OS) like generic Ubuntu/Linux, there could be hundred of processes; all competing for a limitted number of CPU cores. Hence, our process is very often disrupted by other processes. These processes can be from the user or the OS itself. This situation causes undesirable delays in the critical real-time process.

graph LR A[Sensor] -->|measures| B(Sensor Data) B --> C{Process: thinking ...} C -->|Send data| D[Robot] E[Scheduler] --> |hey, pid 1001 is urgent| C

To avoid this issue, one needs a Operating System with real-time capability. A OS that allows certain tasks to have higher priority and thus can be configured to ran in real-time–satisfiying requirements on worst-case latency even under load. Such are Real-time OS (RTOS).

A simple google search leads me to many publicly available RTOS(s). Unfortunately:

  • some are not free (QNX, vxwork);
  • does not support the software ecosystem for robotics (ROS, OpenRAVE). Fortunately it is possible to add the real-time capability to Linux-based OS(s) by using a configured kernel.

Fortunately, there are free alternatives. Real-Time Linux is one such alternative. In this post I will briefly capture steps I have taken to achieve Real-Time capability with Linux.

There is one thing that needs to be clear: there is no such thing as a Real-Time Linux distribution. Rather, one can achieve Real-Time capability by running a Fully Preemptible Linux Kernel instead of the generic Kernel. Fortunately, it is quite simple to do so.

More importantly, tasks can be preempted by the scheduler so that tasks with higher priorities can be ran when they need to be.

Compiling a Real-time Linux Kernel (PREEMPT_RT patch)

First, choose a RT patch from this mirror. I chose version 4.14.78-rt47. The lastest patch as of the time of this writing is 4.19-rt3, unfornately does not work on my machine running Ubuntu 16.04. In any case, the worst that can happen is you have to do the whole compiling/install process again.

Note the Kernel version you have choosen, download the corresponding kernel from this mirror. Both steps can be done via the terminal as below.

cd ~/Downloads
# download patch
wget https://mirrors.edge.kernel.org/pub/linux/kernel/projects/rt/4.14/patch-4.14.78-rt47.patch.xz
# download kernel
wget https://mirrors.edge.kernel.org/pub/linux/kernel/v4.x/linux-4.14.78.tar.xz

Unzipped the archives and patch the kernel with the RT patch.

tar xvf linux-4.14.78.tar.xz
cd linux-4.14.78
xzcat ../patch-4.14.78-rt47.patch.xz | patch -p1 --verbose

We now enable the option Fully Preemptible Kernel (RT). First, install two necessary dependencies.

sudo apt-get install libncurses-dev libssl-dev

Configure the compilation by doing

make menuconfig

You will see a graphical user interface (GUI) show up in the terminal. This GUI contains configurations for compiling the Kernel. The bit that we need is called Preemption Model:

  • Navigate using arrow keys to Processor type and feature, then press Enter;
  • look for Preemption Model, press Enter;
  • choose Fully Preemptible Kernel (RT) option;
  • return to the first screen by pressing Esc multiple times;
  • save .config file, then exit.

Compile the Kernel and install.

make -j20
sudo make modules_install -j20
sudo make install -j20

And that’s it. Reboot, remember to choose the patched Kernel in Advanced Boot Setting, and enjoy!

Remark for 5.x version kernels

The Fully Preemptible Kernel (RT) option seems to have been shifted from Processor type and feature to General setup. Thanks Iain!

Jetson controllers

If you are using a Jetson controller, the above instruction might not be entirely compatible. Fortunately Nvidia official documentation is pretty details on this topic. There are also very helpful resource that are only 1 google away.

Readings

Some useful reads I came across while working on this: