---
# System prepended metadata

title: 2/15 Real-time Programming
tags: [NTURT, electrical_system, experience_sharing]

---

# 2/15 Real-time Programming
###### tags: `experience_sharing` `electrical_system` `NTURT`
##### Author: @heymosbrother 

## Why Using ROS2? 
> ROS2 vs. ROS1

Architecture
![](https://i.imgur.com/Vear8P6.png =650x)
    
- Data Distribution Service (DDS): 
    An API for real-time data distribution and communication between software components in distributed systems.
    Uses a publish/subscribe model to distribute data among components in a system.
    
    

## Hardware Setup
Using Raspberry Pi 4 with [ROS real-time kernel](https://github.com/ros-realtime/ros-realtime-rpi4-image) installed.

## Performance test of ROS2
Using [iRobot ROS 2 Performance Evaluation Framework](https://github.com/irobot-ros/ros2-performance) by running a new workspace, `performance_ws`.

Difficulties:
- Lack of memory while building `performance_ws`
    Solution: cross-compile, adding swap

### Test Objectives
- Latency & Reliability
    ![](https://i.imgur.com/x3LhSmu.png)
- Resources: CPU & Memory usage
    ![](https://i.imgur.com/LHdBBZi.png)
- Conclusion
    ![](https://i.imgur.com/Xm3IWYS.png)

## Real-time Programming Conventions
### Memory Management
To avoid page fault:
> Page fault: 
> In most OS, only important data will be loaded into RAM. As a result, CPU will pause the program execution until the ***page*** is loaded into physical memory. This may cause unpredictable delays.

Add the commands below into `/etc/security/limits.conf` as `sudo`
- Lock memory
    ```cmd
    <your username> - memlock <limit in KB>
    ```
- Elevate the priority of execution
    ```cmd
    <your username> - rtprio <number between 0-98, higher is faster>
    ```
More syntax in C++ program is needed to fully exert the above functionalities.
    
### Programming Methods
Since most unpredictable delays are mostly caused by memory allocation, the goal of the methods mentioned below is to minimize it by using stack memory more rather than heap memory
- Use static or global variables
- Use arrays instead of linked lists
- Minimize the use of loops
- Use ***inline functions*** instead of function calls
    - Inline functions (內嵌函數):
        The default mechanism of function calling is that the computer will record the present memory address of the work stage, jump to the address of the function and then jump back after finishing the funciton execution, which will lead to time burden of the system.
        Rather than the default function calling, the compiler will expand the inline function during program execution.
        Note: this method is only suitable for short and frequently called functions
        
        ![](https://i.imgur.com/3CInDaY.png)

Sample C++ code which complys real-time programming conventions, generated by ChatGPT.
``` Cpp=
#include <iostream>
#include <chrono>
#include <thread>

inline void perform_realtime_task(int i, int* myArray, int arraySize)
{
    std::cout << "Loop iteration " << i << ": " << myArray[i % arraySize] << std::endl;
}

int main()
{
    const int ARRAY_SIZE = 100;
    const int LOOP_TIME_MS = 10;
    const int MAX_LOOPS = 1000;
    int myArray[ARRAY_SIZE];
    
    for (int i = 0; i < ARRAY_SIZE; i++)
    {
        myArray[i] = i;
    }
    
    for (int i = 0; i < MAX_LOOPS; i++)
    {
        // Perform real-time tasks here using an inline function
        perform_realtime_task(i, myArray, ARRAY_SIZE);
        
        // Sleep for a specified amount of time
        std::this_thread::sleep_for(std::chrono::milliseconds(LOOP_TIME_MS));
    }
    
    return 0;
}
```
   
Useful libraries
- `chrono`: 
    Time-related operations. 
    eg. measuring time intervals, representing points in time, calculating time differences.
- `thread`:
    Creating and managing concurrent threads of execution. Makes the multiple threads running in parallel.
    ```Cpp=
    #include <iostream>
    #include <thread>

    // Function to be executed in the new thread
    void thread_func()
    {
        std::cout << "Hello from the new thread!" << std::endl;
    }

    int main()
    {
        std::cout << "Hello from the main thread!" << std::endl;

        // Create a new thread and execute the thread_func function
        std::thread t(thread_func);

        // Wait for the thread to complete
        t.join();

        std::cout << "Exiting main thread!" << std::endl;

        return 0;
    }
    ```
   
## References
- ROS architecture: 
- ROS2 cross compilation: [ROS 2 Cross-compilation official guide](https://docs.ros.org/en/foxy/How-To-Guides/Cross-compilation.html)
- ROS2 Design: [ROS2 real-time systems](https://design.ros2.org/articles/realtime_background.html#memory-management)
- ROS2 real-time programming: [Understand ROS2 real-time programming](https://docs.ros.org/en/humble/Tutorials/Demos/Real-Time-Programming.html)
- C++ inline function: [Inline Functions in C++](https://www.geeksforgeeks.org/inline-functions-cpp/)
- C++ chrono library: [C++ standard library - chrono](https://www.cplusplus.com/reference/chrono/)
- C++ thread library: [C++ standard library - thread](https://www.cplusplus.com/reference/thread/)
- Real-time C++ programming: [How to make C++ more real-time friendly](https://www.embedded.com/how-to-make-c-more-real-time-friendly/)