In this post, I am sharing a C++ Class for Loop Time Histogram. The class measures the loop time and provides its histogram statistics. It is very easy to use and portable. The class provides file output and file output + screen output features.
@Update 04/08/2020: Now histogram is printed in terminal for quick review. For details see the result picture below.
How to use
Simply include the class object, and add a function at the beginning of the loop. Finally, execute a function outputting the result.
Example Code
This example code will execute rand() function multiple times in a loop and measure its loop time.
#include <iostream>
#include <random>
#include "loop_time_stats.h"
using namespace std;
int main()
{
loop_time_stats l("stats.txt",loop_time_stats::output_mode::fileout_and_screenout);
for (int i=0;i<100000;i++){
l.loop_starting_point();
for (int j=0;j<5000;j++){
int k =rand();
}
}
l.store_loop_time_stats();
return 0;
}
Result
The program also saves the result in a text file. I have plotted its result in Excel. The results are shown in the pictures below:
Download
You can download the class, example code, and excel files in the link below:
It is critical for real-time applications to have consistent loop-times with low jitter. There are many different ways of measuring the loop time and generating the histogram (e.g., see cyclictest ( https://github.com/LITMUS-RT/cyclictest ) ), many of those are not portable.
While developing a program, these loop-time measurement codes need to be sometimes activated and sometimes deactivated. Finally they need to be removed at release. It means the code needs to be portable. Object-oriented programming (OOP) concept with C++ class is well suited for this purpose.
Thus, I have embedded all of the sophisticated-looking codes in the class and left only “init”, “loop_start_point”, and “save”. With this simple structure, the user would be easily manage the code with a minimal footage.
For many control applications, multiple RT processes need to run with periodic cycles.
This article presents an example code that enables two RT applications to run with a same periodic cycle. Two RT processes share one shared memory to pass the reference start time of the thread.
Once two processes are synchronized, then two processes control their cycles with “CLOCK_MONOTONIC” clock.
The code for the first app code
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>
#include "shared_memory_base.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];
shared_memory_base comm;
comm.init();
comm.data->first_app_on=1;
struct timespec t_1us;
t_1us.tv_sec = 0; t_1us.tv_nsec=1000;
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 = 0.5 ms * thread_id */
period.tv_sec = 0;
period.tv_nsec = ( 1 ) * 500000; // a x ms
comm.data->first_app_on = 1;
while (comm.data->second_app_on == 0);
clock_nanosleep ( CLOCK_MONOTONIC, 0, &t_1us, NULL ); // wait 1us for second app till it set up the t_ref
t_now = comm.data->t_ref;
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 < 10000; 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%1000==1) printf("second: %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);
comm.detach_shared_memory();
return NULL;
}
int main ()
{
int policy;
struct sched_param prio;
pthread_attr_t attr;
pthread_t tid1;
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_RR;
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(&tid1, &attr, thread_func, (void *)(1)) ){
perror ( "Error: pthread1_create" );
return 1;
}
/* wait for threads to finish */
pthread_join ( tid1, NULL );
return 0;
}
The code for the second application
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>
#include "shared_memory_base.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];
shared_memory_base comm;
comm.init(); // start the shared memory communication
// get the file name
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 = 0.5 ms * thread_id */
period.tv_sec = 0;
period.tv_nsec = ( 1 ) * 500000; // a x ms
comm.data->second_app_on = 1; // let the second app go
while( comm.data->first_app_on == 0 );
clock_gettime ( CLOCK_MONOTONIC, &t_now );
comm.data->t_ref = 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 < 10000; 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%1000==1) printf("first: %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);
comm.detach_shared_memory();
return NULL;
}
int main ()
{
int policy;
struct sched_param prio;
pthread_attr_t attr;
pthread_t tid1;
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_RR;
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(&tid1, &attr, thread_func, (void *)(2)) ){
perror ( "Error: pthread1_create" );
return 1;
}
/* wait for threads to finish */
pthread_join ( tid1, NULL );
return 0;
}
In this post, I am sharing an example of IPC communication with a class using shared memory.
Two processes runs together, and their applications sequentially running. The end of each loop is marked at a shared memory with a “go-flag”. Once the other process see the end-of-the-loop flag, “go-flag”, the process continues the task.
Shared Memory IPC Class
I wrote this class to make the shared memory programming more portable. What you need to do is only to change the struct called “shared_memory_packet. You will see how to use this class in the examples of the next section. You can see the code of “shared_memory_base.h” and “shared_memory_base.cpp” below:
#ifndef SHARED_MEMORY_BASE_H
#define SHARED_MEMORY_BASE_H
#include <sys/ipc.h>
#include <sys/shm.h>
#define DEFAULT_KEY_ID 5700 // default key for shared memory
class shared_memory_base
{
struct shared_memory_packet {
float analog_input[16];
bool go_flag_second_loop = 1;
bool go_flag_first_loop = 1;
};
private:
key_t key;
int shmid = 0;
public:
shared_memory_base();
~shared_memory_base();
shared_memory_packet* data;
void init();
void change_shared_memory_key(key_t k){key= k;} // only use this function before init
void detach_shared_memory();
};
#endif // SHARED_MEMORY_BASE_H
#include "shared_memory_base.h"
shared_memory_base::shared_memory_base()
{
key = ftok("shmfile",DEFAULT_KEY_ID);
}
shared_memory_base::~shared_memory_base(){
detach_shared_memory();
}
void shared_memory_base::init(){
// shmget returns an identifier in shmid
shared_memory_packet temp;
shmid = shmget(key, sizeof(temp),0666|IPC_CREAT);
// shmat to attach to shared memory
data = (shared_memory_packet*) shmat(shmid,(void*)0,0);
}
void shared_memory_base::detach_shared_memory(){
shmdt(data);
shmctl(shmid,IPC_RMID,nullptr);
}
Ping-pong Sequence between Two Processes
In this example, “first_app.cpp” the number of an integer variable incrementally, and change the “go_flag_second_loop” to be one. In “second_app.cpp” the number of an integer variable is reduced, and change the “go_flag_first_loop” to be one. With this two go_flags two processes run sequencially.
mkdir build
cd build
cmake ../shared_memory_example
make
More discussion
Concurrency problem is a very well-known and challenging problem. There are many other nice techniques other than this one. Particularly after C++11, the standard C++ has introduced a nice set of concurrent thread and process running functions. In addition, this example is not the best code for efficient applications.
I found a very good reference explaining Concurrency, Parallelism, Threads, Processes, Async and Sync. For the details, read the article in the link below:
In this post, I will share an example C/C++ code demonstrating a method to safely delete dynamically allocated memory when a user terminates the application by Ctrl-C.
Problem
First let’s review a code which includes a problem. The code dynamically allocate a memory for the variable a. The code has delete[] function, but the application cannot arrive there due to the infinite loop which is very common in may applications. If a user terminates the application with Ctrl-C, then the memory will be leaked.
#include <iostream>
int main(){
signal(SIGINT, myInterruptHandler);
double* a;
a = new double [1000];
std::cout << "press ctrl-c\n" ;
while(1){ }
delete[] a;
}
The figure below shows the execution results.
As you can see the, the free memory continuously is reduced every time after the termination of the application by Ctrl-C.
Solution by Using Signal
In Linux system, if a user press Ctrl-C, a signal is sent to the process from the OS. We can catch the signal and make a different routine. One example is as below:
There is another function called “sigaction()”. It seems more robust and well -defined. But it seems to need more lines of codes. Thus, I decided to use signal. For the details, please read this post .
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).
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.
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.
ADC ICs (e.g., ADS1256, ADS1246) often outputs an analog voltage value in the format of 2’s complement. I am sharing a simple function and example that convert the format of two’s complement into signed long int.
for the detailed knowledge on the format of 2’s complement, please refer this site.
In this post, I will explain how to derive a dynamic equation with Lagrange Equation by MATLAB with Examples. As an example, I will derive a dynamic model of a three-DOF arm manipulator (or triple pendulum). Of course you may get a dynamic model for a two-DOF arm manipulator by simply removing several lines. I am attaching demo codes for both two and three DOF arm manipulators.
If you know all theories and necessary skills and if you just want source code, you can just download from here.
In the attached file, “Symb_Development_3DOF.m” generates a dynamic model. “main_sim_three_dof_arm.m” runs a simulation. You may get a result like this.
1. Example system
Let’s suppose a three DOF arm manipulator shown in the below figure. I am assuming all of masses (M1, M2, M3) exist at the end of links for simplicity. Three actuators exist at each joint, and directly actuate the torques (u1,u2,u3). The manipulator kinematics is governed by three joint angles (q1, q2, q3).
three DOF arm manipulator
2. Theoretical Background
We will get a dynamic equation of this system by using Lagrangian mechanics. If you do not have a background knowledge of Lagrangian mechanics, please refer here.
The general dynamic equation is obtained by
Where, T is the total kinetic energy, V is the total potential energy of the system. where is the generalized force, t is time, is the generalized coordinates, is the generalized velocity. For the example of three-DOF arm manipulator problem, is the torque at the j-th joint, is the angle of the j-th joint, is the angular velocity of the j-th joint.
3. Using Matlab symbolic toolbox
First, let’s define the symbols.
I am using x to represent q, xd for , xdd for L is the length of each link. u is the torque of each joint. g is the gravity constant.
In the attached file, “Symb_Development_3DOF.m” generates a dynamic model. “main_sim_three_dof_arm.m” runs a simulation. Then, you can get this result.
So far, I have explained how to derive a Lagrange Equation by MATLAB with Examples.I hope that this post helps your project and save your time. Please leave a message if you have any question.
Update on 02/21/2016
I updated some code and posting about typo. “simple” -> “simplify” There is no function “simple” Now all programs are running well.