RTAI-ROS documentation

Requirements

For code generation only RTAI-ROS is required. To compile and run the generated program it requires:

  • RTAI (tested with v4.0)
  • ROS (tested with Hydro)

For the development version (> 1.0):

  • libpopt for command line parsing (on Ubuntu it named libpopt-dev)

Installation

  1. Copy the rtairos directory to $(MATLABROOT)/rtw/c/, where $(MATLABROOT) is the root of your Matlab installation.

  2. In Matlab change to rtairos directory and run setup

    >> matlabroot
    ans =
    /opt/matlab
    >> cd /opt/matlab/rtw/c/rtairos
    >> setup
    

    This compiles all S-Functions of RTAI-ROS and adds the devices subdirectory to the search path. Make sure you have write permissions on rtairos.

  3. In rtairos.tmf change the variables MATLAB_ROOT, LINUX_HOME, RTAIDIR, COMEDI_HOME, and ROS_HOME to your needs. Be sure to set it for the target system where you want to compile your code.

    • During code generation the variable |>MATLAB_ROOT<| will be expanded by the TLC to the Matlab installation directory. On a linux system this is normally /opt/matlab (sometimes /usr/local/matlab).
    • You can leave the variables LINUX_HOME, RTAIDIR, and COMEDI_HOME unchanged if rtai-config is in the search path and can be found during build.

    If you use Windows for code generation remove also the following lines:

    |>START_EXPAND_RULES<|%.o : |>EXPAND_DIR_NAME<|/%.c
        gcc -c $(CFLAGS) $<
    
    |>END_EXPAND_RULES<|
    

Uninstallation

To uninstall just remove the rtairos directory. Matlab normally removes invalid directories from search path. To remove the rtairos directory manually from search path, run

>> rmpath $(MATLABROOT)/rtw/c/rtairos

Usage

The usage of RTAI-ROS will be explained using the example examples/rosdemo.mdl.

_images/rosdemo.png

Generate code

  1. Open your Simulink model, in our case rosdemo.mdl.
  2. Open the configuration dialog Simulation → Configuration Parameters → Real-Time Workshop and select rtairos.tlc as System target file. If you don’t want to compile the code, select also Generate code only.
  3. Click on Generate code. This creates the subdirectory rosdemo_rtairos in your current directory containig the generated source code.
  4. Copy the directory rosdemo_rtairos to your RTAI Linux system.
_images/rtw-config.png

Build

  1. Change to the source directory rosdemo_rtairos. If you generated your code on a Windows system create a symbolic link to the make file:

    ln -s rosdemo.mk Makefile
    
  2. Build the program:

    make
    

Run

  1. Start the ROS master:

    roscore &
    
  2. Set the ROS_MASTER_URI environment variable:

    export ROS_MASTER_URI=http://localhost:11311
    
  3. Start the demo:

    ../rosdemo
    

Connect with ROS

Now you can connect to the running program using ROS, e.g:

  • Show all registered topics and services:

    rosnode info /rosdemo
    
  • Read from topic:

    rostopic echo /demo/uy
    
  • Write to topic:

    rostopic pub -1 /demo/v std_msgs/Float64 2
    
  • Read all parameters of the model from parameter server:

    rosparam get /rosdemo
    

    This will give you the following output:

    Config: {P1: 10.0, P3: 1.0, P4: 1.0, P5: 3.0}
    Constant: {Value: 1.0}
    Environment_Controller:
    Switch_Control: {Value: 0.0}
    Environment_Controller1:
    Switch_Control: {Value: 0.0}
    Integrator: {InitialCondition: 0.0}
    Log: {P1: 2.0, P3: 0.0}
    Publisher: {P1: 4.0, P3: -1.0}
    Publisher1: {P1: 1.0, P3: -1.0}
    Publisher2: {P1: 5.0, P3: -1.0}
    Publisher3: {P1: 1.0, P3: -1.0}
    Publisher4: {P1: 1.0, P3: -1.0}
    Publisher5: {P1: 1.0, P3: -1.0}
    Publisher6: {P1: 2.0, P3: -1.0}
    Pulse_Generator: {Amplitude: 1.0, Period: 10000.0, PulseWidth: 5000.0}
    Repeating_Sequence:
    Look_Up_Table1:
    InputValues: [0.0, 2.0, 4.0, 6.0]
    Table: [0.0, 2.0, 2.0, 0.0]
    Service: {P2: -1.0}
    Service1: {P2: -1.0}
    Subscriber: {P1: 1.0, P3: 1.0, P4: -1.0, P5: 0.0}
    Subscriber1: {P1: 1.0, P3: 0.0, P4: -1.0, P5: 0.0}
    
  • Change the parameters of the square wave signal:

    rosparam set /rosdemo/Pulse_Generator '{Amplitude: 0.5, Period: 5000, PulseWidth: 2500}'
    rosservice call /rosdemo/set_parameters
    
  • Set source to trapezoidal signal:

    rosservice call /demo/trapezoid
    

Instead of using command line tools you can use rqt, check examples/rosdemo.perspective for a demo perspective.

_images/rosdemo-rqt.png

Special services

The ROS node provides up to three special services:

  • /rosdemo/refresh_parameters to write model parameters to the parameter server. This can be avoided via config block.
  • /rosdemo/set_parameters to write modified parameters on the parameter server to the model. This can be set via config block.
  • /rosdemo/start to start the real-time process if the program was started with -w.

Parameters

There are various arguments for the program which can be shown by

../rosdemo -h

The generated program supports also parameter mapping

../rosdemo name:=new_name

To run multiple programs on the same machine it is required to set the name of the host interface task (default IFTASK) with

../rosdemo -n TASK2

to avoid conflicts. The number of blocks useable on a machine is restricted by the number of registrable RTAI objects set during the installation of RTAI. You can read this number from MAX_SLOTS in /proc/rtai/name. For the moment every block requires two RTAI objects, one for the shared memory and one for the semaphore.

Blocks

_images/rtairos-blocks.png

Following blocks are available to connect with ROS.

  • Publisher/Subscriber to read/write topics.

    Available message types:

    • std_msg/Bool
    • std_msg/Int32
    • std_msg/Float64
    • std_msg/Float64MultiArray
    • std_msg/Time
    • geometry_msgs/Point
    • geometry_msgs/PointStamped
    • geometry_msgs/Twist
    • geometry_msgs/TwistStamped
    • geometry_msgs/Pose2D
  • Service to make a service call with request and reply message of type std_msg/Empty.

  • Transformation publisher to publish tf messages.

  • Joint state publisher to publish joints.

  • Joystick subscriber to read from joy node.

  • Config to configure following parameters of the ROS node:

    • Rate (default: 100 ms)
    • Namespace (default: none)
    • Publisher queue size (default: 10)
    • Subscriber queue size (default: 10)
    • If parameters should be exposed to parameter server and can be changed with /NODE/set_parameters (default: read only).
  • Logger to send a log message triggert by a raising edge.

There are additional blocks to read a Sensoray s526 counter and write to a RTAI-FIFO. All other blocks are taken from RTAI-Lab.

Advanced usage

Extend own S-Function

The following code shows the base structure to add log functionality to your own S-Function:

#ifndef MATLAB_MEX_FILE
#include <ros_block.h>
#endif

static void mdlInitializeSizes(SimStruct *S) {
    ssSetNumIWork(S, 1);
    ssSetNumPWork(S, 2);
}

#define MDL_START
static void mdlStart(SimStruct *S) {
    #ifndef MATLAB_MEX_FILE
    rosBlockInitResult_t block = registerRosBlock(S, "rosout", LOGGER, 0);
    block.shm->msg.level = LOG_ERROR;
    ssSetIWorkValue(S, 0, block.num);
    ssSetPWorkValue(S, 0, (void *)block.shm);
    ssSetPWorkValue(S, 1, (void *)block.sem);
    #endif
}

static void mdlOutputs(SimStruct *S, int_T tid) {
    #ifndef MATLAB_MEX_FILE
    rosShmData_t *shm = (rosShmData_t *)ssGetPWorkValue(S, 0);
    SEM *sem = (SEM *)ssGetPWorkValue(S, 1);
    if (error) {
        if (rt_sem_wait_if(sem) != 0) {
            memcpy(shm->msg.text, "Error occurred", MAX_LOG_MSG_SIZE);
            shm->msg.state = NEW_VALUE;
            rt_sem_signal(sem);
        }
    }
    #endif
}

static void mdlTerminate(SimStruct *S) {
    #ifndef MATLAB_MEX_FILE
    cleanRosBlock(ssGetIWorkValue(S, 0));
    #endif
}

Add own message types

For the moment this requires to change the source code. The necessary steps are shown using geometry_msgs/Vector3 as an example.

  1. In include/ros_defines.h add a new preprocessor variable, e.g.:

    #define PUBLISHER_VECTOR3 42    // or
    #define SUBSCRIBER_VECTOR3 42
    
  2. Include the header file in rtmain.cpp:

    #undef RT
    #include <geometry_msgs/Vector3.h>
    #define RT
    
  3. For a publisher add a new case to class RosPublisher:

    void publish() {
        ...
        } else if (subType == PUBLISHER_VECTOR3) {
            geometry_msgs::Vector3 msg;
            msg.x = shmData.data[0];
            msg.y = shmData.data[1];
            msg.z = shmData.data[2];
            pub.publish(msg);
        }
    }
    

    For a subscriber add a new callback function to RosSubscriber:

    void callback(const geometry_msgs::Vector3 msg) {
        if (!this->sem_wait()) return;
        shm->data[0] = msg.x;
        shm->data[1] = msg.y;
        shm->data[2] = msg.z;
        this->sem_signal();
    }
    
  4. In function rosInterface() add an initialization block:

    // Subscribers
    } else if (rosBlockConfigs[i].type == SUBSCRIBER) {
        ...
        } else if (subscriber->subType == SUBSCRIBER_VECTOR3) {
            subscriber->sub = nh.subscribe<geometry_msgs::Vector3>(subscriber->name,
                rosConfig.subStackSize, &RosSubscriber::callback, subscriber);
    
    // Publishers
    } else if (rosBlockConfigs[i].type == PUBLISHER) {
        ...
        } else if (publisher->subType == PUBLISHER_VECTOR3) {
            publisher->pub = nh.advertise<geometry_msgs::Vector3>(publisher->name,
                rosConfig.pubStackSize);
    

Files

  • ros_block.c: Helper functions used by ROS blocks

  • rtairos_genfiles.tlc: Additional script for the Target Language Compiler; creates the symbolic link on unix systems.

  • rtairos.tlc: Main script for the Target Language Compiler

  • rtairos.tmf: Makefile template

  • rtmain.cpp: Main program

  • setup.m: Matlab installation script

  • devices/
    • rtairos.mdl: Simulink library

    • S-Functions for Comedi:
      • sfun_comedi_counter_read.c: Read counter
      • sfun_comedi_data_read.c: Read analog input
      • sfun_comedi_data_write.c: Write analog output
      • sfun_comedi_dio_read.c: Read digital input
      • sfun_comedi_dio_write.c: Write digital output
    • sfun_rtai_fifo.c: S-Function to write FIFOs

    • S-Functions for ROS:
      • sfun_ros_config.c: Config block
      • sfun_ros_joint_state.c: Joint state publisher
      • sfun_ros_joy.c: Joystick subscriber
      • sfun_ros_log.c: Logger
      • sfun_ros_publisher.c: Publisher
      • sfun_ros_service.c: Service
      • sfun_ros_subscriber.c: Subscriber
      • sfun_ros_tf.c: Transformation publisher
    • S-Functions for RTAI-Lab (see RTAI-Lab documentation):
      • sfun_rtai_automatic_log.c
      • sfun_rtai_led.c
      • sfun_rtai_log.c
      • sfun_rtai_meter.c
      • sfun_rtai_scope.c
      • sfun_rtai_synchronoscope.c
    • slblocks.m: Configuration of the simulink library

  • examples/
    • rtaitest.mdl: RTAI-Lab example
    • rosdemo.mdl: Example model; see Usage
    • rosdemo.perspective: A example perspective for rqt.
  • include/
    • ros_block.h: Helper functions used by ROS blocks
    • ros_defines.h: Defines and structs used by the main program and blocks.