0
$\begingroup$

Ubuntu 22.04, ROS2 Humble

Hi,

Is there a programmatic way for a ros2 cpp node to resolve the full path of its parent package?

For instance I have a package that contains a cpp node as shown below

/home/az/ros2_ws/src/ros2_cpp_package/src/cpp_node.cpp

I can find the path to the home directory using cstdlib and this command std::string homeDir = getenv('HOME') in cpp_node.cpp.

However the remaining part /ros2_ws/src/ros2_cpp_package/, I had to hardcode which I want to avoid to make my code easily usable by other users when they would download it from my github repo.

Any help and suggestions would be most appreciated.

With best, Azmyin

$\endgroup$

3 Answers 3

1
$\begingroup$

I'm not sure exactly what files you're trying to find, but there are some tools that can help: get_package_share_directory!

See example in Nav2 [1]. Any files stored in the shared path of the package can be found (e.g. xml, yaml, anything you install()-ed there). There are a few other methods [2] you can use as well to obtain file path locations, so hopefully that should help.

PS: they also exist in python3 as well

[1] https://github.com/ros-planning/navigation2/blob/main/nav2_bt_navigator/src/navigators/navigate_through_poses.cpp#L60

[2] https://github.com/ament/ament_index/tree/rolling/ament_index_cpp/include/ament_index_cpp

$\endgroup$
1
  • $\begingroup$ Thanks for the links. Yea, I should have clarified. The ros2 cpp node in the question above, looks for a number of local files to load some configuration parameters. These files are located in different local directories within the parent package. Hence I wanted to find the parent path in a way that it can be used by any user without requiring them to manually updating the path after downloading my ros2 package. $\endgroup$ Commented Dec 23, 2023 at 14:06
1
$\begingroup$

The following worked for me.

The core idea is we export a shell environment variable that any C++ / Python package can access. An example is shown below

  1. Create a shell script called ros2_config.sh. I created in home directory as shown below
#!/bin/bash

# Source ROS Humble primitives and packages from main workspace
source /opt/ros/humble/setup.bash

# Source colcon related variables and files
source /usr/share/colcon_argcomplete/hook/colcon-argcomplete.bash

# Find path to home directory
HOME_DIRECTORY=$HOME

# Type in the name of the workspace you want to use
# Make sure the "/" symbol is placed before the name of the workspace
ROS2_WS="/ros2_ws"

# Programmatically build path to the workspace
ROS2_WS_PATH="$HOME_DIRECTORY$ROS2_WS" 

# Export ROS2_WS as an environment variable
# Export allows other programs to access $ROS2_WS_PATH$ variable
export ROS2_WS_PATH

# Source the workspace.
source "$ROS2_WS_PATH/install/setup.bash"

# Local ROS Master
#export ROS_IP=167.96.128.47
export ROS_MASTER_URI=http://localhost:11311

echo ""
echo -e "ROS2_WS_PATH: $ROS2_WS_PATH"
echo -e "ROS NETWORK CONFIGURATION"
echo -e "ROS_MASTER_URI\t= $ROS_MASTER_URI" 
# echo -e "ROS_IP\t= $ROS_IP" 
echo ""

  1. Configure .bashrc file to source this shell script every time a new terminal is opened or .bashrc file is sourced. One way is to open the .bashrc file with a text editor and adding the following line to towards the end
# Source all ROS 2 related stuff
source ~/ros2_config.sh
  1. Source .bashrc file to load this changes or close and open a terminal

  2. The path to workspace is now accessible by looking for the ROS2_WS_PATH variable. An example from a C++ node constructor is shown below

// Extract path to ros2_workspace
    const char* cstr = std::getenv("ROS2_WS_PATH");
    if (cstr != nullptr) {
        std::string ros2_ws_path(cstr);
        packagePath = ros2_ws_path + "/src/orb_slam3_ros2/";
        std::cout << "packagePath: " << packagePath << std::endl;
    } else {
        throw std::runtime_error("Environment variable ROS2_WS_PATH is not set");
    }

Hope this helps.

With best Azmyin

$\endgroup$
1
$\begingroup$

If you wish to retrieve some files in the installed package then get_package_share_directory is the way to go. It is available in the ament_index_cpp package.

On the opposite if you want to get a path relative to the source then it can be done with CMake, without anything related to ROS:

add_definitions(-DMY_PKG_ROOT_PATH="${CMAKE_CURRENT_SOURCE_DIR}")

your C++ code will have access to this definition as a const char*, you can easily change it to e.g. a std::string with const std::string root_path{MY_PKG_ROOT_PATH};

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.