Skip to main content

Introduction

Pulsar EM can launch ROS2 applications and make it run as adaptive application. EM can handle ROS2 application life cycle. launching, terminating as specified in EM function group.

About This Tutorial

This sample application make you learn about integrating and launching ROS2 applications with Pulsar SDK. With this tutorial you make ROS2 application as adaptive application.

With this tutorial, we are providing guide lines for making ROS2 application as adaptive application.

This tutorial make you get familiar about below topics

  • Creating ROS2 workspace and ROS2 package
  • Integrating SDK libraries with ROS2 application.
  • Building ROS2 Native application
  • Writing script file instead of application execution file
  • Execution Manifest file modifications
  • Building
  • Running
  • Output

You can find sample applications at <SDK_Path>/samples/ros/ folder.

note
  1. This tutorial was created in thought of Your system is already installed with ROS2 setup.
  2. We developed and tested Pulsar SDK adaptive applications using ROS2:Humble Hawksbill version Please install ROS2:Humble Hawksbill from here

1. Creating ROS2 workspace and Package

  1. Create workspace as given below. for more details about creating ROS2 workspace check here

    $ source /opt/ros/humble/setup.sh
    $ mkdir -p ~/ros2_ws/src
    $ cd ~/ros2_ws/src
  2. Create package as given below. For more details, follow package creation steps specified here

    $ cd ~/ros2_ws/src
    $ ros2 pkg create --build-type ament_cmake --license Apache-2.0 --node-name my_node my_package
    $ cd ~/ros2_ws

Above command will create a simple Hello World type executable in the package.

2. Integrating SDK libraries with ROS2 application

  1. Now we need to write the code. In src folder, you can find my_node.cpp file. please copy below code snippet in that file.

    #include <cstdio>
    #include <thread>
    #include <chrono>
    #include <unistd.h>
    #include <signal.h>

    #include <executionclient.hpp>
    #include <phmclient.hpp>
    #include "logger.hpp"

    // Creating bool variable as flag to control while loop
    static bool isRunning = true;

    void sigterm_handler(int signum) {
    printf("Received signal : %d\n", signum);
    // Do any necessary cleanup here

    // Setting flag value to false when signal received.
    isRunning = false;
    }

    int main(int argc, char ** argv) {
    (void) argc;
    (void) argv;
    uint32_t incrementVar = 0U;

    signal(SIGTERM, sigterm_handler);

    printf("hello world my_package package\n");
    printf("CPP process ID : %d\n", getpid());
    printf("CPP parent process ID : %d\n", getppid());

    nebula::platform::Logger logger_ { nebula::platform::Logger("my_node") };
    auto &execClient = nebula::exec::client::ExecutionClient::getInstance(nebula::exec::client::ApplicationType::APP_TYPE_ROS);
    auto &phmClient = nebula::phm::client::PHMClient::getInstance(nebula::phm::client::ApplicationType::APP_TYPE_ROS);


    execClient.reportExecutionState(nebula::exec::client::ExecutionState::ESRunning);


    while (isRunning) {
    usleep(300*1000);
    phmClient.reportCheckPoint(11);
    printf("my node sleep at position : %d\n", incrementVar);
    logger_.LogDebug() << "[my_node::main] my node sleep at position :" << incrementVar++;
    }

    execClient.reportExecutionState(nebula::exec::client::ExecutionState::ESTerminated);

    printf("my_node: At End of ROS application\n");

    return 0;
    }

  2. And then we need to modify CMakeLists.txt file to link with Pulsar SDK header files and libraries. below is the sample snippet to link with Pulsar SDK

    cmake_minimum_required(VERSION 3.8)
    project(my_package)

    if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
    add_compile_options(-Wall -Wextra -Wpedantic)
    endif()

    # find dependencies
    find_package(ament_cmake REQUIRED)
    # uncomment the following section in order to fill in
    # further dependencies manually.
    # find_package(<dependency> REQUIRED)

    #Set PULSAR_SDK_ROOT as prefix path. so libraries and header files can be found for compilation.
    SET(CMAKE_PREFIX_PATH $ENV{PULSAR_SDK_ROOT})

    add_executable(my_node src/my_node.cpp)

    find_package(neblogger REQUIRED)
    find_package(nebosal REQUIRED)
    find_package(em_client REQUIRED)
    find_package(phm_client REQUIRED)

    target_link_libraries(my_node em_client phm_client neblogger nebosal)
    target_include_directories(my_node PUBLIC
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
    $<BUILD_INTERFACE:${CMAKE_PREFIX_PATH}/include/em_client>
    $<BUILD_INTERFACE:${CMAKE_PREFIX_PATH}/include/phm_client>
    $<BUILD_INTERFACE:${CMAKE_PREFIX_PATH}/include/neblogger>
    $<BUILD_INTERFACE:${CMAKE_PREFIX_PATH}/include/nebosal>
    $<BUILD_INTERFACE:${CMAKE_PREFIX_PATH}/include/nebcore>
    $<INSTALL_INTERFACE:include>)

    target_link_directories(my_node PUBLIC ${CMAKE_PREFIX_PATH}/lib/)

    target_compile_features(my_node PUBLIC c_std_99 cxx_std_17) # Require C99 and C++17

    install(TARGETS my_node
    DESTINATION lib/${PROJECT_NAME})


    if(BUILD_TESTING)
    find_package(ament_lint_auto REQUIRED)
    # the following line skips the linter which checks for copyrights
    # comment the line when a copyright and license is added to all source files
    set(ament_cmake_copyright_FOUND TRUE)
    # the following line skips cpplint (only works in a git repo)
    # comment the line when this package is in a git repo and when
    # a copyright and license is added to all source files
    set(ament_cmake_cpplint_FOUND TRUE)
    ament_lint_auto_find_test_dependencies()
    endif()

    ament_package()

3. Building ROS2 Native application

  1. Now, our ROS2 application is ready to build. Build the package

    # Move to root of workspace
    $ cd ~/ros2_ws

    # Set environment variable 'PULSAR_SDK_ROOT' in console as shown in given below
    $ export PULSAR_SDK_ROOT=<SDK_Path>

    # build the workspace for particular package
    $ colcon build --packages-select my_package
  2. When build started, you can observe below lines on console

    alt ros_app_build_start

  3. Once build is completed, console shows below lines

    alt ros_app_build_complete

  4. Now, ROS2 application is ready to launch. for testing you can launch it here from console.

    # Move to root of workspace
    $ cd ~/ros2_ws

    # Set ROS2 variables
    $ source ./install/local_setup.sh

    #exporting library path
    $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:<SDK_Path>/lib/

    #Launch ROS2 application
    $ ros2 run my_package my_node
  5. Console prints logs as shown in below. ROS2 applications starts, but you can find errors as application try to communicate with Pulsar Execution Manager and PHM services.

    alt ros_app_direct_launch_logs

  6. Now, we have to make this ROS2 application launch by Execution manager. Next steps will guide for that.

note

you can download sample ROS2 package here

4. Writing Script file

This section guides you about writing script file to launch ROS2 applications by Execution Manager.

4.1 Use of Script file

General Adaptive applications in opt directory has below structure. Consider we have adaptive application called appFirst.

appFirst
├── bin
│ └── appFirst
└── etc
└── exec_config.json

Here bin/appFirst is executable file for adaptive application appFirst

In case of ROS2 application, we can't launch ROS2 application directly as ROS2 applications need to be configured with few ROS2 environment variables.

So User need to write a script file instead of binary. The ROS2 application to be launched by EM has below structure

appRos
├── bin
│ └── my_node.sh
└── etc
└── exec_config.json

When ever Function group of ROS2 application is active, EM will start ROS2 application by running 'my_node.sh' in this case.

4.2 Sample Script file

Below you can find script file used in appRos application.

    #!/bin/bash
echo "Starting ROS my_node script"
echo $SHELL
echo "Current process ID : $$"
echo "parent process ID : $PPID"

#Moving to ROS application directory.
#For example, if you create ROS workspace using above steps. your workspace directory is ros_ws folder in your system.
cd <ROS2 Workspace directory>

#Set User's home directory path
# Example : 'export HOME=/home/xxxx'
export HOME=<User's home directory path>

#Running ROS2 setup script file
#Read ROS documentation for initializing & launching ROS2 applications for more detail information
source /opt/ros/humble/setup.sh
source ./install/local_setup.sh

#Exporting Pulsar lib directory, so ROS2 application can find libraries
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:<SDK_Path>/lib/

#Running ROS2 my_node application.
exec ros2 run my_package my_node

4.3 Script file contents

This section guides you about content of script file

  1. Change current directory to ROS2 workspace created in 1st Step

    $ cd <Your Path>/ros2_ws/
  2. exporting $HOME environment variable. Set with your home directory.

    $ export HOME=<User's home directory path>

    #Example : 'export HOME=/home/xxxx'

  3. Running ROS2 setup script files.

    $ source /opt/ros/humble/setup.sh       < Global ROS2 setup script file>
    $ source ./install/local_setup.sh < Local workspace setup script file>
  4. exporting 'LD_LIBRARY_PATH' environment variable for Pulsar SDK library path. so ROS2 application can access Pulsar EM client , PHM client, logger and other modules.

    $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:<SDK_Path>/lib/

5. Execution Manifest file Modifications

  1. Keep script file name and as ROS2 package name

  2. Should provide absolute path of script file ('my_node.sh' file in above case) in startupConfigs/options in execution Manifest file.

        "options" : [
    "<path to appRos application directory>/bin/my_node.sh"
    ],

Building ROS2 application

  1. As we are using script file instead of binary, Compilation is not required. but to generate required folder structure, please run below commands

    This step is optional. User can make required folder structure.

    $ cd <SDK_Path>/samples/ros/appRos/
    $ mkdir build
    $ cd build
    $ cmake -DCMAKE_INSTALL_PREFIX=<Output_Path_To_Generated_Binaries> ..
    $ make install
  2. Once you run above steps, It generates required folder structure opt folder at given <Output_Path_To_Generated_Binaries> directory path

    appRos
    ├── bin
    │ └── my_node.sh
    └── etc
    └── exec_config.json

Running ROS2 application

You can launch the appRos sample application by running execution manager. please provide '-d' option with path to appRos folder

  • Run appRos
$ cd <SDK_Path>
$ export LD_LIBRARY_PATH=<SDK_Path>/lib
$ ./bin/executionManager -d ./bin/ -d <Output_Path_To_Generated_Binaries/opt>

Output

You find SDK starting logs as shown in previous (appFirst & diagnostics) tutorials .

Once my_node script file launched by EM, you can find below log on console

alt ros_app_creation_log

You find below logs when script starts executing

alt ros_app_script_start_log

And you find below logs, when ROS2 application starts

alt ros_app_start_logs

While running

alt ros_app_running_logs

alt ros_app_running_logs2