Tag Archives: control

RT Periodic Thread Code and Scheduler Policy and Priority

in this post, I am going to share an example code creating two threads running with a periodic cycle in an RT Preempt Linux.

You can download the code in this link.

https://github.com/queristq/rt_periodic_thread/archive/master.zip or you can git clone by git clone https://github.com/queristq/rt_periodic_thread.git

To build the code,

  • mkdir build
  • cd build
  • cmake ..
  • make

RT Performance between SCHED_RT and SCHED_IDLE

In the code, I have created two threads, and tested the RT performance for two different thread schedule policy between SCHED_RT and SCHED_IDLE. The figure below shows the result. The blue line shows the log10-scaled histogram of the loop time, and the orange line shows the log10-scaled histogram of the loop time. As shown in the plot, SCHED_RT made low jitters in the periodic loops. The test environment was not strictly controlled (I did internet browsing… while the loop was running).

1

RT Performance over Different Thread Priorities

I have conducted similar tests with different thread priority. I have selected the same thread policy SCHED_FIFO, and the priority of two threads were chosen to 1 and 99 respectively. The jitters of the each loop is shown in the figure below. As shown in the figure, interestingly the difference was very minor. Once you see the details, you can see the result of Priority 1 is slightly better.

2

If you want a full result, you can see the test result in the attached excel sheet.

Example code

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>

#define TIMESPEC_ADD(A,B) /* A += B */ \
    do {                                   \
    (A).tv_sec += (B).tv_sec;          \
    (A).tv_nsec += (B).tv_nsec;        \
    if ( (A).tv_nsec >= 1000000000 ) { \
    (A).tv_sec++;                  \
    (A).tv_nsec -= 1000000000;     \
    }                                  \
    } while (0)

#define TIMESPEC_SUB(A,B) /* A -= B */ \
    do {                                   \
    (A).tv_sec -= (B).tv_sec;          \
    (A).tv_nsec -= (B).tv_nsec;        \
    if ( (A).tv_nsec < 0 ) {           \
    (A).tv_sec--;                  \
    (A).tv_nsec += 1000000000;     \
    }                                  \
    } while (0)


void *thread_func ( void *param )
{
    FILE *fp;
    char filename_fp[50];

    long thread_id = (long) param;

    sprintf (filename_fp, "%ld%s", thread_id, ".txt");
    fp = fopen(filename_fp, "w");//opening file

    struct timespec t_next, period, t_now, t_prev, t_diff;

    /* period = 1 ms * thread_id */
    period.tv_sec = 0;
    period.tv_nsec = ( 1 ) * 500000; // a x ms

    clock_gettime ( CLOCK_MONOTONIC, &t_now );
    t_next = t_now;
    t_prev = t_now;

    int t_jitter[100];
    for (int i=0;i<100;i++) t_jitter[i] = 0;
    int t_j = 0;

    for ( int i = 0; i < 100000; i++ )
    {
        clock_gettime ( CLOCK_MONOTONIC, &t_now );
        t_diff = t_now;
        TIMESPEC_SUB ( t_diff, t_prev );
        t_prev = t_now;
        t_j = t_diff.tv_nsec / 10000;
        if (t_j<0) t_jitter[0]++;
        else if (t_j>99) t_jitter[99]++;
        else t_jitter[t_j]++;
        if(i%10000==1) printf("%d\n",i);
        TIMESPEC_ADD ( t_next, period );
        clock_nanosleep ( CLOCK_MONOTONIC, TIMER_ABSTIME, &t_next, NULL );
    }

    for (int i=0;i<100;i++) {
        printf("%d ",t_jitter[i]);
        fprintf(fp, "%d\n",t_jitter[i]);
    }
    fclose(fp);
    return NULL;
}

int main ()
{
    int policy;
    struct sched_param prio;
    pthread_attr_t attr;

    pthread_t tid1;
    pthread_t tid2;

    policy = SCHED_OTHER;
    if (pthread_setschedparam( pthread_self(),policy, &prio )){
        perror ("Error: pthread_setschedparam (root permission?)");
        exit(1);
    }

    pthread_attr_init( &attr);
    pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED);
    policy = SCHED_FIFO;
    pthread_attr_setschedpolicy( &attr, policy);
    prio.sched_priority = 99; // priority range should be btw -20 to +19
    pthread_attr_setschedparam(&attr,&prio);

    if ( pthread_create(&tid1, &attr, thread_func, (void *)(1)) ){
        perror ( "Error: pthread1_create" );
        return 1;
    }

    pthread_attr_init( &attr);
    pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED);
    policy = SCHED_FIFO;
    pthread_attr_setschedpolicy( &attr, policy);
    prio.sched_priority = 1; // priority range should be btw -20 to +19
    pthread_attr_setschedparam(&attr,&prio);

    if ( pthread_create(&tid2, &attr, thread_func, (void *)(2)) ){
        perror ( "Error: pthread2_create" );
        return 1;
    }

    /* wait for threads to finish */
    pthread_join ( tid1, NULL );
    pthread_join ( tid2, NULL );

    return 0;
}

If you are interested in how to make an RT Linux, please see another post of mine.

I found a very good material to study deeper on RT thread.

  • https://csperkins.org/teaching/2004-2005/rtes5/lecture10.pdf
  • http://retis.sssup.it/~lipari/courses/str09/10.rtprogramming-handout.pdf

If you have any questions on this code or this post, please leave a reply. Then, good luck!

[1] Nanosleep, http://man7.org/linux/man-pages/man2/nanosleep.2.html

[2] Timespec basic operation, http://www.zemris.fer.hr/~leonardo/srsv/skripta/src/periodic-tasks-2.c

Tutorial: How to make RT Preempt Linux with Ubuntu 18.04.02

In this tutorial, I will present how to make a RT Preempt Linux with Ubuntu 18.04.02

1. install Ubuntu 18.04.02 in your computer. Let me skip the details since there are so many other tutorials for this.

2. Once the install is finished. Download Linux kernel and RT Patch

  • Linux Kernel Download at

https://mirrors.edge.kernel.org/pub/linux/kernel/v4.x/

Screenshot from 2020-02-20 23-20-00

  • RT patch download at https://mirrors.edge.kernel.org/pub/linux/kernel/projects/rt/4.4/

Screenshot from 2020-02-20 23-21-54

3. Prepare to compile the kernel

cd Downloads/
xz -cd linux-4.4.208.tar.xz | tar xvf -
cd linux-4.4.208/
xzcat ../patch-4.4.208-rt191.patch.xz | patch -p1
sudo apt install libncurses5-dev build-essential cmake libssl-dev git flex bison
make menuconfig
  • Set “High Resulution Timer Support” Screenshot from 2020-02-21 00-08-07 Screenshot from 2020-02-21 00-08-13
  • Set “Fully Preemptible Kernel (RT)

Screenshot from 2020-02-21 00-08-47 Screenshot from 2020-02-21 00-09-26 Screenshot from 2020-02-21 00-09-43

  • (optional) set Local version nameScreenshot from 2020-02-21 00-10-24 Screenshot from 2020-02-21 00-10-28
  • Save the config fileScreenshot from 2020-02-21 00-11-08

4. Compile and install the kernel ( WARNING: It takes very long time)

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

Here -jx is to specify the number of CPU cores, if you just choose a high number, it go with your all CPU cores.

5. Grub setting

sudo gedit /etc/default/grub

Then, edit the text as below:

To select the booting option in GRUB

GRUB_TIMEOUT_STYLE=hidden -> GRUB_TIMEOUT_STYLE=menu

To increase the time out for selecting a menu

GRUB_TIMEOUT=0 -> GRUB_TIMEOUT=3

To reduce the visual effect

GRUB_CMDLINE_LINUX_DEFAULT=”quiet splash” -> GRUB_CMDLINE_LINUX_DEFAULT=”quiet”

If you want to boot without graphical desktop (terminal mode)

GRUB_CMDLINE_LINUX=”” -> GRUB_CMDLINE_LINUX=”3″

5. Rebooting

sudo update-grub
sudo reboot

6. Select RT-preempt kernel in GRUB

select Advanced and RT-Linux

(Optional)  If you want to customize GRUB more, then use grub-customizer (grub editor with GUI)

sudo add-apt-repository ppa:danielrichter2007/grub-customizer 
sudo apt update
sudo apt install grub-customizer

Other readings

Now you are ready to develop or run an RT application on RT Preempt Linux. If you need to know how to write a RT thread running with a periodic cycle, read another article of mine.

Good luck!

One-year observation of my baby with the eyes of control engineer

As a control engineer, I see different features from my one-year-old baby, Chloe. When she was first born, she did not have a model for her biomechanical system, and the controller in her brain was immature. Nonetheless, her finger did not vibrate or diverge, which commonly occur in traditional control systems. The kinematics of her finger is same with that of a three-link pendulum, commonly referred to describe a chaotic dynamic system. She had never tried to make it stable, no, actually she disturbed the system. But, her biomechanical systems were amazingly stable. For the past one year, her control ability has been dramatically improved. Now she can walk and interact with highly uncertain dynamic objects like another baby. It is an extremely difficult control task. Furthermore, in someday, she would be able to drive a car and to manage (control) a business. She has a great system, modeling ability, and controller, three essential elements for control. As a control engineer, I cannot help being surprised and admiring.

Feb 11, 2014

-Mok-

Sliding Mode Control (SMC), Robust control algorithm for nonlinear system

In this article, I am going to write about the Sliding Mode Control (SMC) algorithm.

Sliding Mode Control algorithm is a robust controller for nonlinear systems.

Robust control means that even though the system model has a certain error, if the controller can control the system, we say that the controller is robust.

SMC has two fundamental ideas.

1. To attract the system states to the surface.

2. To make the state slide on the surface toward the origin.

To explain the above two ideas more easily, let’s assume a typical control problem.

\dot x = f_1 (x,\dot x)   — (1)

\ddot x = f_2 (x, \dot x) + u

y=Cx — (2) if it is nonlinear, you need to know Lie Derivatives.

To achieve the first idea, we need to define a surface like the below. (Let’s assume that y is a scalar and differentiable.) 

s(x)=a_0 e + a_1 \dot{e}  where  e=y-y_d — (3)

Here we need to select a_0 and a_1 to make y->0 as t-> inf,s=0. You will see the reason after more several lines.

Let’s take the derivative of s(x) w.r.t. x. Then we can get the below equation.

\dot{s}(x)=a_0 \dot e + a_1 \ddot e  — (4)

In addition, if we add the additional term –\eta \text{sign}(s) we can obtain the below equation,

\dot{s}(x)=a_0 \dot e + a_1 \ddot e=-\eta \text{sign}(s) — (5)

Through a simple Lyapunov theorem, we can easily prove s-> 0 at t->inf .

if s=0, e-> 0 and \dot(e)-> 0, because we selected a_0 and a_1 to be like this.

Let’s look at (5),

a_0 \frac{d}{dt}(y-y_d)+a_1 \frac{d^2}{dt^2}(y-y_d)=-\eta \text{sign}(s)

=> C(a_0 \dot x +a_1 \ddot x)=-\eta \text{sign}(s)

=>C(a_0 f_1 +a_1 (f_2+u)))=-\eta \text{sign}(s)

=>u=((-\eta \text{sign} (s))/C - a_0 f_1)/a_1 -f_2

With this control input, we can control a nonlinear system with SMC.

it is difficult to explain quickly within short explanations…., if you need more explanation or questions, please leave me a reply.

 

Feedback linearization control (FBL) for nonlinear system control proof, practical implementation, and easy example part1

This article explains about Feedback linearization control (FBL) method for control of a nonlinear system. This is one of the easiest strategy to control nonlinear systems, but pretty powerful. The basic idea is that we can cancel control input by manipulating control input. The below is its proof. fbl_1 fbl_2

 

This is the most basic concept to explain easily. If the nonlinear system is not fully controllable, we should use another strategy which finds reduced order manifold (ROM). About the more advanced technique and examples will be explained in the next articles.

 

—————————————————————————————————————————–

I am Youngmok Yun, and writing about robotics theories and my research.

My main site is http://youngmok.com, and Korean ver. is  http://yunyoungmok.tistory.com.

—————————————————————————————————————————–