Robotics StackExchange | Archived questions

how can I use the Xenomai functions in ROS?

Hi there,

I trying to use Xenomai functions in a C++ file in a ROS(1) package.

The hardware plataform used is a Raspberry Pi 3

The goal is to create a Xenomai task with ROS functions inside.

As a entry point, I download the example from Xenomai website.

The makefile for a simple task program, outside catkin workspace, is:

SKIN=alchemy
MAIN_SRC=ex01
TARGET=ex01

LM=-lm

CFLAGS := $(shell xeno-config --skin=alchemy --cflags)
LDFLAGS := $(LM) $(shell xeno-config --skin=alchemy --ldflags)
CC := $(shell xeno-config --cc)

$(TARGET): $(MAIN_SRC).c
    $(CC) -o $@ $< $(CFLAGS) $(LDFLAGS)

The xeno-config --skin=alchemy --cflags returns arm-linux-gnueabihf-gcc.

In the catkin workspace I create a simple package named beginner_tutorials based in the example from:

http://wiki.ros.org/ROS/Tutorials/WritingPublisherSubscriber%28c%2B%2B%29.

The program files are located in "src" subdirectory from package: talker.cpp and listener.cpp. In this sources was added the Xenomai include files to use its functions.

In "CMakeLists.txt" located in "beginner_tutorials", was added this commands to make possible compile and link the Xenomai lib to my executable:

execute_process(COMMAND xeno-config --skin=alchemy --cflags OUTPUT_VARIABLE XENO_CFLAGS)
execute_process(COMMAND xeno-config --skin=alchemy --ldflags OUTPUT_VARIABLE XENO_LDFLAGS)

SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${XENO_CFLAGS}")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${XENO_LDFLAGS}")

add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})

add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})

message(STATUS "C COMPILER") # too see compiler and used and flags
message(STATUS ${CMAKE_CXX_COMPILER})
message(STATUS "XENOMAI CFLAGS")
message(STATUS ${XENO_CFLAGS})
message(STATUS "XENOMAI LDFLAGS")
message(STATUS ${XENO_LDFLAGS})

When I go to "~/catkinws" and tip `catkinmake`, the results are as folow:

Base path: /root/catkin_ws
Source space: /root/catkin_ws/src
Build space: /root/catkin_ws/build
Devel space: /root/catkin_ws/devel
Install space: /root/catkin_ws/install
####
#### Running command: "make cmake_check_build_system" in "/root/catkin_ws/build"
####
-- Using CATKIN_DEVEL_PREFIX: /root/catkin_ws/devel
-- Using CMAKE_PREFIX_PATH: /opt/ros/kinetic
-- This workspace overlays: /opt/ros/kinetic
-- Using PYTHON_EXECUTABLE: /usr/bin/python
-- Using Debian Python package layout
-- Using empy: /usr/bin/empy
-- Using CATKIN_ENABLE_TESTING: ON
-- Call enable_testing()
-- Using CATKIN_TEST_RESULTS_DIR: /root/catkin_ws/build/test_results
-- Found gmock sources under '/usr/src/gmock': gmock will be built
-- Found gtest sources under '/usr/src/gmock': gtests will be built
-- Using Python nosetests: /usr/bin/nosetests-2.7
-- catkin 0.7.11
-- BUILD_SHARED_LIBS is on
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- ~~  traversing 1 packages in topological order:
-- ~~  - beginner_tutorials
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- +++ processing catkin package: 'beginner_tutorials'
-- ==> add_subdirectory(beginner_tutorials)
-- C COMPILER
-- /usr/bin/c++

-- XENOMAI CFLAGS
-- -I/usr/xenomai/include/cobalt -I/usr/xenomai/include -march=armv7-a -mfloat-abi=hard -mfpu=neon -ffast-math -D_GNU_SOURCE -D_REENTRANT -D__COBALT__ -I/usr/xenomai/include/alchemy

-- XENOMAI LDFLAGS
-- -Wl,--no-as-needed -Wl,@/usr/xenomai/lib/modechk.wrappers -lalchemy -lcopperplate /usr/xenomai/lib/xenomai/bootstrap.o -Wl,--wrap=main -Wl,--dynamic-list=/usr/xenomai/lib/dynlist.ld -L/usr/xenomai/lib -lcobalt -lmodechk -lpthread -lrt  

-- Configuring done
-- Generating done
-- Build files have been written to: /root/catkin_ws/build
####
#### Running command: "make -j4 -l4" in "/root/catkin_ws/build"
####
[ 50%] Linking CXX executable /root/catkin_ws/devel/lib/beginner_tutorials/listener
[ 50%] Linking CXX executable /root/catkin_ws/devel/lib/beginner_tutorials/talker
c++: fatal error: no input files
compilation terminated.
c++: fatal error: no input files
compilation terminated.
beginner_tutorials/CMakeFiles/listener.dir/build.make:115: recipe for target '/root/catkin_ws/devel/lib/beginner_tutorials/listener' failed
make[2]: *** [/root/catkin_ws/devel/lib/beginner_tutorials/listener] Error 4
CMakeFiles/Makefile2:946: recipe for target 'beginner_tutorials/CMakeFiles/listener.dir/all' failed
make[1]: *** [beginner_tutorials/CMakeFiles/listener.dir/all] Error 2
make[1]: *** Waiting for unfinished jobs....
beginner_tutorials/CMakeFiles/talker.dir/build.make:115: recipe for target '/root/catkin_ws/devel/lib/beginner_tutorials/talker' failed
make[2]: *** [/root/catkin_ws/devel/lib/beginner_tutorials/talker] Error 4
CMakeFiles/Makefile2:909: recipe for target 'beginner_tutorials/CMakeFiles/talker.dir/all' failed
make[1]: *** [beginner_tutorials/CMakeFiles/talker.dir/all] Error 2
Makefile:138: recipe for target 'all' failed
make: *** [all] Error 2
Invoking "make -j4 -l4" failed

From what I could understand, the catkin did not find the Xenomai files needed for linking. That's right? Another thing is that catkin uses g++ for compile, but this is a problem?

What I can do to solve this?

Thanks.

EDIT 1:

I can do compile with the following commands in the package's CMakeLists.txt:

execute_process(COMMAND xeno-config --skin=alchemy --cflags OUTPUT_VARIABLE XENO_CFLAGS)
execute_process(COMMAND xeno-config --skin=alchemy --ldflags OUTPUT_VARIABLE XENO_LDFLAGS)

SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${XENO_CFLAGS}")
string(STRIP ${CMAKE_CXX_FLAGS} CMAKE_CXX_FLAGS)

SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--wrap=main -Wl,--no-as-needed -Wl,@/usr/xenomai/lib/modechk.wrappers -lalchemy -lcopperplate /usr/xenomai/lib/xenomai/bootstrap.o -Wl,--dynamic-list=/usr/xenomai/lib/dynlist.ld -L/usr/xenomai/lib -lcobalt -lmodechk -lpthread -lrt")

add_executable(talker src/talker.cpp )
target_link_libraries(talker ${catkin_LIBRARIES} )

This time, I compile just talker for simplicity.

The output from catkin_make was:

Base path: /root/catkin_ws
Source space: /root/catkin_ws/src
Build space: /root/catkin_ws/build
Devel space: /root/catkin_ws/devel
Install space: /root/catkin_ws/install
####
#### Running command: "make cmake_check_build_system" in "/root/catkin_ws/build"
####
-- Using CATKIN_DEVEL_PREFIX: /root/catkin_ws/devel
-- Using CMAKE_PREFIX_PATH: /root/catkin_ws/devel;/opt/ros/kinetic
-- This workspace overlays: /root/catkin_ws/devel;/opt/ros/kinetic
-- Using PYTHON_EXECUTABLE: /usr/bin/python
-- Using Debian Python package layout
-- Using empy: /usr/bin/empy
-- Using CATKIN_ENABLE_TESTING: ON
-- Call enable_testing()
-- Using CATKIN_TEST_RESULTS_DIR: /root/catkin_ws/build/test_results
-- Found gmock sources under '/usr/src/gmock': gmock will be built
-- Found gtest sources under '/usr/src/gmock': gtests will be built
-- Using Python nosetests: /usr/bin/nosetests-2.7
-- catkin 0.7.11
-- BUILD_SHARED_LIBS is on
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- ~~  traversing 1 packages in topological order:
-- ~~  - beginner_tutorials
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- +++ processing catkin package: 'beginner_tutorials'
-- ==> add_subdirectory(beginner_tutorials)

-- Configuring done
-- Generating done
-- Build files have been written to: /root/catkin_ws/build
####
#### Running command: "make -j4 -l4" in "/root/catkin_ws/build"
####
[ 50%] Building CXX object beginner_tutorials/CMakeFiles/talker.dir/src/talker.cpp.o
[100%] Linking CXX executable /root/catkin_ws/devel/lib/beginner_tutorials/talker
/usr/bin/ld: warning: libboost_system.so.1.54.0, needed by /usr/lib/gcc/arm-linux-gnueabihf/4.9/../../../arm-linux-gnueabihf/libconsole_bridge.so, may conflict with libboost_system.so.1.55.0
/usr/bin/ld: warning: libboost_thread.so.1.54.0, needed by /usr/lib/gcc/arm-linux-gnueabihf/4.9/../../../arm-linux-gnueabihf/libconsole_bridge.so, may conflict with libboost_thread.so.1.55.0
[100%] Built target talker 

In main function I try initialize ros::init and inside the created task in talker the anothers ros functions for publish are used:

#include "ros/ros.h"
#include "std_msgs/String.h"

#include <sstream>

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/mman.h>

#include <alchemy/task.h>
#include <alchemy/timer.h>

#include  <trank/rtdk.h>

RT_TASK demo_task;

void demo(void *arg)
{
  RT_TASK *curtask;
  RT_TASK_INFO curtaskinfo;

  // inquire current task
  curtask=rt_task_self();
  rt_task_inquire(curtask,&curtaskinfo);
  // print task name
  rt_printf("Task name : %s \n", curtaskinfo.name);

  rt_printf("PASS_0\n");

  ros::NodeHandle n;

  rt_printf("PASS_1\n");

  ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);

  ros::Rate loop_rate(10);

  int count = 0;
  while (ros::ok())
  {
    std_msgs::String msg;

    std::stringstream ss;
    ss << "hello world " << count;
    msg.data = ss.str();


    rt_printf("PASS_%d\n", count);
    ROS_INFO("%s", msg.data.c_str());


    chatter_pub.publish(msg);

    ros::spinOnce();

    loop_rate.sleep();
    ++count;
  }
}


int main(int argc, char **argv)
{

 char  str[10] ;

 struct args main_args;

  ros::init(argc, argv, "talker");

 // Perform auto-init of rt_print buffers if the task doesn't do so
  rt_print_auto_init(1);

  // Lock memory : avoid memory swapping for this program
  mlockall(MCL_CURRENT|MCL_FUTURE);

  rt_printf("start task\n");

  /*
   * Arguments: &task,
   *            name,
   *            stack size (0=default),
   *            priority,
   *            mode (FPU, start suspended, ...)
   */
  sprintf(str,"hello");
  rt_task_create(&demo_task, str, 100000000, 50, 0);

  /*
   * Arguments: &task,
   *            task function,
   *            function argument
   */
  rt_task_start(&demo_task, &demo, 0);

}

However, on execution, this error are throw:

rosrun beginner_tutorials talker
start task
Task name : hello 
PASS_0
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::lock_error> >'
  what():  boost: mutex lock failed in pthread_mutex_lock: Invalid argument
Aborted

From the code, can be seen that this exception are thrown when "NodeHandle n" is created. The question now is: why this exception are thrown?

EDIT 2:

I change the system for one with just one libboost version (1.58). As can be seen, the binary use just one version of libboost.

ldd talker 
    linux-vdso.so.1 =>  (0x7ef8b000)
    /usr/lib/arm-linux-gnueabihf/libarmmem.so (0x76f66000)
    libalchemy.so.0 => /usr/xenomai/lib/libalchemy.so.0 (0x76f06000)
    libcopperplate.so.0 => /usr/xenomai/lib/libcopperplate.so.0 (0x76eec000)
    libcobalt.so.2 => /usr/xenomai/lib/libcobalt.so.2 (0x76ec3000)
    libmodechk.so.0 => /usr/xenomai/lib/libmodechk.so.0 (0x76eb1000)
    libpthread.so.0 => /lib/arm-linux-gnueabihf/libpthread.so.0 (0x76e8d000)
    librt.so.1 => /lib/arm-linux-gnueabihf/librt.so.1 (0x76e77000)
    libroscpp.so => /opt/ros/kinetic/lib/libroscpp.so (0x76d48000)
    libboost_filesystem.so.1.58.0 => /usr/lib/arm-linux-gnueabihf/libboost_filesystem.so.1.58.0 (0x76d27000)
    libboost_signals.so.1.58.0 => /usr/lib/arm-linux-gnueabihf/libboost_signals.so.1.58.0 (0x76d05000)
    librosconsole.so => /opt/ros/kinetic/lib/librosconsole.so (0x76cd1000)
    librosconsole_log4cxx.so => /opt/ros/kinetic/lib/librosconsole_log4cxx.so (0x76caf000)
    librosconsole_backend_interface.so => /opt/ros/kinetic/lib/librosconsole_backend_interface.so (0x76c9d000)
    liblog4cxx.so.10 => /usr/lib/arm-linux-gnueabihf/liblog4cxx.so.10 (0x76b57000)
    libboost_regex.so.1.58.0 => /usr/lib/arm-linux-gnueabihf/libboost_regex.so.1.58.0 (0x76aa0000)
    libxmlrpcpp.so => /opt/ros/kinetic/lib/libxmlrpcpp.so (0x76a7c000)
    libroscpp_serialization.so => /opt/ros/kinetic/lib/libroscpp_serialization.so (0x76a69000)
    librostime.so => /opt/ros/kinetic/lib/librostime.so (0x76a3a000)
    libcpp_common.so => /opt/ros/kinetic/lib/libcpp_common.so (0x76a24000)
    libboost_system.so.1.58.0 => /usr/lib/arm-linux-gnueabihf/libboost_system.so.1.58.0 (0x76a11000)
    libboost_thread.so.1.58.0 => /usr/lib/arm-linux-gnueabihf/libboost_thread.so.1.58.0 (0x769e6000)
    libboost_chrono.so.1.58.0 => /usr/lib/arm-linux-gnueabihf/libboost_chrono.so.1.58.0 (0x769d0000)
    libboost_date_time.so.1.58.0 => /usr/lib/arm-linux-gnueabihf/libboost_date_time.so.1.58.0 (0x769b3000)
    libboost_atomic.so.1.58.0 => /usr/lib/arm-linux-gnueabihf/libboost_atomic.so.1.58.0 (0x769a1000)
    libconsole_bridge.so.0.2 => /usr/lib/arm-linux-gnueabihf/libconsole_bridge.so.0.2 (0x7698d000)
    libstdc++.so.6 => /usr/lib/arm-linux-gnueabihf/libstdc++.so.6 (0x7687f000)
    libm.so.6 => /lib/arm-linux-gnueabihf/libm.so.6 (0x76807000)
    libgcc_s.so.1 => /lib/arm-linux-gnueabihf/libgcc_s.so.1 (0x767df000)
    libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0x766f3000)
    /lib/ld-linux-armhf.so.3 (0x76f7b000)
    libapr-1.so.0 => /usr/lib/arm-linux-gnueabihf/libapr-1.so.0 (0x766c6000)
    libaprutil-1.so.0 => /usr/lib/arm-linux-gnueabihf/libaprutil-1.so.0 (0x7669d000)
    libicui18n.so.55 => /usr/lib/arm-linux-gnueabihf/libicui18n.so.55 (0x76504000)
    libicuuc.so.55 => /usr/lib/arm-linux-gnueabihf/libicuuc.so.55 (0x763e7000)
    libuuid.so.1 => /lib/arm-linux-gnueabihf/libuuid.so.1 (0x763d3000)
    libdl.so.2 => /lib/arm-linux-gnueabihf/libdl.so.2 (0x763c0000)
    libcrypt.so.1 => /lib/arm-linux-gnueabihf/libcrypt.so.1 (0x76381000)
    libexpat.so.1 => /lib/arm-linux-gnueabihf/libexpat.so.1 (0x76359000)
    libicudata.so.55 => /usr/lib/arm-linux-gnueabihf/libicudata.so.55 (0x74a92000)

However, the same error appears on execution:

'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::lock_error> >'
      what():  boost: mutex lock failed in pthread_mutex_lock: Invalid argument
    Aborted

Asked by matheus.pinto on 2018-08-24 08:03:58 UTC

Comments

Ignoring the issues with the build process: can you please explain what you want to achieve? The whole of roscpp is most likely not hard real-time safe. It uses memory allocation, threads, locks and a lot of system calls that will make Xenomai very unhappy.

Creating a real-time safe ..

Asked by gvdhoorn on 2018-08-24 08:08:59 UTC

.. node is possible, but not in the way you're showing here.

Asked by gvdhoorn on 2018-08-24 08:09:13 UTC

First, I would like to see if it is possible to use xenomai functions inside the catkin. Then I would see details of how to make communication as predictable as possible (not necessarily hard).About what you said: what other means to achieve real time with ros1?

Asked by matheus.pinto on 2018-08-24 09:09:38 UTC

Please see RTROS – A real-time extension to the Robot Operating System from ROSCon16. It goes into some detail as to what the performance of ROS1 is when trying to use it for (even soft) real-time tasks.

Asked by gvdhoorn on 2018-08-24 09:12:15 UTC

First, I would like to see if it is possible to use xenomai functions inside the catkin

catkin == cmake.

I would recommend you try and find some information on how to compile and link Xenomai programs with CMake. The procedure for Catkin would be identical.

Asked by gvdhoorn on 2018-08-24 09:13:12 UTC

I am aware that catkin is basically the cmake. However, as I did not find any information in other communities, I ended up resorting to the ROS group.

Regarding the RT-ROS that you passed, I did not find any place where I can download the project.

Asked by matheus.pinto on 2018-08-24 20:25:27 UTC

However, as I did not find any information in other communities, I ended up resorting to the ROS group.

building Xenomai Apps with CMake appears to be a discussion on the Xenomai mailing list about just this subject.

Asked by gvdhoorn on 2018-08-25 02:49:49 UTC

Regarding the RT-ROS that you passed, I did not find any place where I can download the project.

I did not refer you to that presentation for that reason. I wanted to provide you with a source of information, and show you that others have done similar work.

Asked by gvdhoorn on 2018-08-25 02:50:23 UTC

From the code, can be seen that this exception are thrown when "NodeHandle n" is created. The question now is: why this exception are thrown?

I'm guessing, but this could be due to an ABI incompatibility between the Boost version that your Xenomai libs are linked against and the one that ROS ..

Asked by gvdhoorn on 2018-08-29 01:47:04 UTC

.. is linked against.

You link 1.54 via ROS and 1.55 via something else. Might be worthwhile to see where that difference comes from.

Do you have a Boost version installed from sources on your platform?

Asked by gvdhoorn on 2018-08-29 01:48:49 UTC

Do you have a Boost version installed from sources on your platform?

In this point, I dont know. But probably yes. I took the system image from: [http://www.cs.ru.nl/lab/xenomai/]

Asked by matheus.pinto on 2018-08-29 11:05:37 UTC

Xenomai uses a technique where it wraps pthread and similar POSIX libraries with versions that are real-time safe. IIRC, it also checks whether what you're wrapping is not violating determinism by injecting some checks.

It could be that the completely non real-time safe ROS libraries ..

Asked by gvdhoorn on 2018-08-30 08:32:14 UTC

.. are doing something strange which causes your process to abort with that exception.

You'll probably have to debug and find out where that exception is being thrown.

I don't think I can be of much assistance here. Perhaps asking on the Xenomai mailing list is an idea?

Asked by gvdhoorn on 2018-08-30 08:33:11 UTC

Answers