-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add ROS2 standalone build option * Separate ros2_standalone CMakeLists & add configurable rpath * Polish build tools to compile extenstions easier * Handle command nvcc not found * Add setup script for windows * Adjust README to setup_win script * Restore support for cyclonedds * Add documentation for ROS2 extension * Change steps order in windows building section * Add script for applying required changes in rclcpp * Merge setup.bash and setup_win_py into setup.py * Apply suggestions from code review Co-authored-by: Piotr Rybicki <[email protected]> * ROS2 standalone build - setup.py review suggestions (#89) * Fix indentation in setup.py * Fix indentation, introduce main() * Refactor setup.py script * Apply suggestions from code review Co-authored-by: Mateusz Szczygielski <[email protected]> * Inform about default --make and --ninja args Co-authored-by: Mateusz Szczygielski <[email protected]> * Fix CUDA_MIN_VER_PATCH for Windows * Add $ORIGIN explanation * Add comments to ros2_standalone CMakeLists * Fix README building typos * Fix regex for python libs on Windows Co-authored-by: Piotr Rybicki <[email protected]>
- Loading branch information
Showing
11 changed files
with
514 additions
and
116 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
# RGL ROS2 extension | ||
|
||
The extension introduces the node to publish [PointCloud2](https://docs.ros2.org/foxy/api/sensor_msgs/msg/PointCloud2.html) messages to ROS2. RGL creates a ROS2 node named `RobotecGPULidar` and registers publishers based on constructed RGL nodes. | ||
|
||
Supported ROS2 distributions: | ||
- Humble | ||
|
||
Supported DDS implementations for ROS2 standalone build: | ||
- Eclipse Cyclone DDS | ||
- eProsima Fast DDS | ||
|
||
## Building | ||
|
||
RGL ROS2 extension can be built in two flavors: | ||
|
||
- **standalone** - ROS2 installation is not required on the target machine. RGL build will include all required ROS2 dependencies. | ||
- **overlay** - Assumes existence of supported ROS2 installation on the target machine. RGL will try to use the existing installation of ROS2 dependencies. | ||
|
||
|
||
### Ubuntu 22 | ||
|
||
#### Prerequisites | ||
|
||
- Requirements listed in the main [README](../README.md) (section `Building on Ubuntu`). | ||
- ROS2 installed on the system and sourced. | ||
- For standalone build: | ||
- ROS2 `cyclonedds` and `fastrtps` packages. | ||
- `patchelf` tool. | ||
```bash | ||
apt install -y ros-${ROS_DISTRO}-cyclonedds ros-${ROS_DISTRO}-rmw-cyclonedds-cpp | ||
apt install -y ros-${ROS_DISTRO}-fastrtps ros-${ROS_DISTRO}-rmw-fastrtps-cpp | ||
apt install patchelf | ||
``` | ||
|
||
#### Steps for overlay | ||
1. Use script `setup.py` with option `--with-ros2`. | ||
|
||
#### Steps for standalone | ||
1. Use script `setup.py` with option `--with-ros2-standalone` | ||
- You can specify run-time search path(s) of RGL dependencies by adding option `--lib-rpath <paths>`. This can be useful if you want RGL to search for ROS2 libraries in a different directory than RGL, e.g., if you work with a library providing its own ROS2 libraries such as [ROS2ForUnity](https://github.com/RobotecAI/ros2-for-unity). | ||
2. Copy all ROS2 libraries from `<build-dir>/ros2_standalone/` to `libRobotecGPULidar.so` location (or location defined with `--lib-rpath`). | ||
|
||
#### Tips for integrating RGL + ROS2 standalone with Unity and [ROS2ForUnity](https://github.com/RobotecAI/ros2-for-unity) plugin. | ||
1. Build RGL with command: | ||
```bash | ||
./setup.py --with-ros2-standalone --lib-rpath \$ORIGIN/.plugin --make="-j" | ||
``` | ||
*$ORIGIN represents the directory in which an object (library) originated. It is resolved at run-time.* | ||
2. Copy library `<build-dir>/libRobotecGPULidar.so` to the appropriate directory in your RGLUnityPlugin. | ||
3. Create a new directory named `.plugin` in location where `libRobotecGPULidar.so` is. | ||
4. Copy all ROS2 libraries from `<build-dir>/ros2_standalone/` to the newly created `.plugin` directory. | ||
|
||
Unity ignores dynamic libraries in directories named `.plugin`. This way, ROS2 standalone builds for `ROS2ForUnity` and `RGL` will be separated and not loaded twice by Unity. | ||
|
||
### Windows | ||
|
||
#### Prerequisites | ||
|
||
- Requirements listed in the main [README](../README.md) (section `Building on Windows`). | ||
- ROS2 installed on the system and sourced. | ||
- Fixed ROS2 logging macros in rclcpp package to make it compile with C++20. More about this bug: [github PR](https://github.com/ros2/rclcpp/pull/2063). | ||
- Use `fix_ros2_humble.py` script to apply those changes: | ||
```bash | ||
py ros2_standalone\fix_ros2_humble.py <your-path-to-ros2> | ||
``` | ||
- For standalone build: | ||
- If you have installed ROS2 from pre-built binaries, there is `rmw_cyclonedds_cpp` package missing. You need to build this one from the source: | ||
1. Make sure you have installed [ROS2 prerequisites](https://docs.ros.org/en/humble/Installation/Alternatives/Windows-Development-Setup.html#installing-prerequisites). | ||
2. Good practice is to disable Windows path limits, [see](https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=registry). | ||
3. Run `x64 Native Tools Command Prompt for VS 2019`, setup development folder (e.g., `C:\rosrmw`), clone ROS2 repos, and build: | ||
```bash | ||
md \rosrmw\src | ||
cd \rosrmw | ||
vcs import --input https://raw.githubusercontent.com/ros2/ros2/humble/ros2.repos src | ||
colcon build --merge-install --packages-up-to rmw_cyclonedds_cpp | ||
``` | ||
4. Before building RGL, source `rosrmw` workspace: `call C:\rosrmw\install\setup.bat`. | ||
|
||
|
||
#### Steps for overlay | ||
1. Run `x64 Native Tools Command Prompt for VS 2019` and navigate to RGL repository. | ||
2. Run `python setup.py --with-ros2` command to build RGL with ROS2 extension. | ||
|
||
#### Steps for standalone | ||
1. Run `x64 Native Tools Command Prompt for VS 2019` and navigate to RGL repository. | ||
2. Run `python setup.py --with-ros2-standalone` command to build RGL with ROS2 extension and install ROS2 libraries. | ||
3. Copy all ROS2 libraries from `<build-dir>/ros2_standalone/` into `RobotecGPULidar.dll` location, or extend environment variable `Path` appropriately. | ||
|
||
#### Tips for integrating RGL + ROS2 standalone with Unity and [ROS2ForUnity](https://github.com/RobotecAI/ros2-for-unity) plugin. | ||
1. Build RGL with ROS2 standalone as described above. | ||
2. Copy `<build-dir>/RobotecGPULidar.dll` and all depend libraries located in `<build-dir>` to appropriate directory in your RGLUnityPlugin. | ||
3. Copy all ROS2 libraries from `<build-dir>/ros2_standalone/` to `Ros2ForUnity\Plugins\Windows\x86_64` directory. Skip for duplicates. | ||
|
||
In this case, RGL's ROS2 standalone build is dependent on ROS2ForUnity's ROS2 standalone build. RobotecGPULidar library will find ROS2 because ROS2ForUnity sets environment variable `Path` for the ROS2 libraries. | ||
|
||
## Usage | ||
|
||
Each RGL node for ROS2 publishing must be connected to a format node that defines fields and their layout in the binary data. For example, to publish PointCloud2 message with fields XYZ and DISTANCE, the code should look as follow: | ||
```c | ||
... | ||
rgl_node_t nodeFormat = nullptr, nodeRos2 = nullptr; | ||
std::vector<rgl_field_t> fieldsToPublish = { RGL_FIELD_XYZ_F32, RGL_FIELD_DISTANCE_F32 }; | ||
rgl_node_points_format(&nodeFormat, fieldsToPublish.data(), fieldsToPublish.size()) | ||
rgl_node_points_ros2_publish(&nodeRos2, "example_topic", "example_frame"); | ||
rgl_graph_node_add_child(..., nodeFormat); | ||
rgl_graph_node_add_child(nodeFormat, nodeRos2); | ||
``` | ||
## API documentation | ||
More details can be found [here](../include/rgl/api/extensions/ros2.h). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
# This file is based on https://github.com/RobotecAI/ros2cs/blob/master/src/ros2cs/ros2cs_core/CMakeLists.txt | ||
|
||
find_program(PATCHELF "patchelf") | ||
if(UNIX) | ||
if(NOT PATCHELF) | ||
message(FATAL_ERROR "'patchelf' executable not found. Linux standalone version requires 'patchelf' for patching 'runpath' of certain libraries. You can install it via 'sudo apt install patchelf'") | ||
else() | ||
message("'patchelf' found in ${PATCHELF}") | ||
endif() | ||
endif() | ||
set(REQ_STANDALONE_LIBS "") | ||
set(REQ_STANDALONE_DLLS "") | ||
|
||
# Get location for library target | ||
macro(fetch_target_lib _target) | ||
string(REGEX REPLACE "::" "_" _target_normalized ${_target}) | ||
set(_locations IMPORTED_LOCATION_NONE IMPORTED_LOCATION_NOCONFIG IMPORTED_LOCATION_RELEASE IMPORTED_LOCATION_RELWITHDEBINFO IMPORTED_LOCATION_DEBUG) | ||
foreach(_location ${_locations}) | ||
get_target_property(${_target_normalized}_LIB_PATH ${_target} ${_location}) | ||
if(NOT "${${_target_normalized}_LIB_PATH}" STREQUAL "${_target_normalized}_LIB_PATH-NOTFOUND") | ||
break() | ||
endif() | ||
endforeach() | ||
endmacro() | ||
|
||
# Extend REQ_STANDALONE_LIBS with _library_name dependencies | ||
macro(get_standalone_dependencies _library_name) | ||
find_package(${_library_name} REQUIRED) | ||
|
||
# Get cyclonedds DDSC | ||
if("${_library_name}" STREQUAL "CycloneDDS") | ||
if(WIN32) | ||
fetch_target_lib(CycloneDDS::ddsc) | ||
fetch_target_lib(CycloneDDS::idl) | ||
list(APPEND REQ_STANDALONE_LIBS | ||
${CycloneDDS_ddsc_LIB_PATH} | ||
${CycloneDDS_idl_LIB_PATH} | ||
${CycloneDDS_dds_security_ac_LIB_PATH} | ||
${CycloneDDS_dds_security_auth_LIB_PATH} | ||
${CycloneDDS_dds_security_crypto_LIB_PATH}) | ||
elseif(UNIX) | ||
fetch_target_lib(CycloneDDS::ddsc) | ||
list(APPEND REQ_STANDALONE_LIBS ${CycloneDDS_ddsc_LIB_PATH}) | ||
endif() | ||
endif() | ||
|
||
# Get rmw_cyclonedds_cpp | ||
if("${_library_name}" STREQUAL "rmw_cyclonedds_cpp") | ||
fetch_target_lib(rmw_cyclonedds_cpp::rmw_cyclonedds_cpp) | ||
list(APPEND REQ_STANDALONE_LIBS ${rmw_cyclonedds_cpp_rmw_cyclonedds_cpp_LIB_PATH}) | ||
endif() | ||
|
||
# We skip python libs | ||
set(PYTHON_LIB_REGEX ".*python[0-9]*\.[0-9]*\.so") | ||
if(WIN32) | ||
set(PYTHON_LIB_REGEX ".*(l|L)ib(s|)\/python[0-9]*\.lib" ) | ||
endif() | ||
foreach(entry ${${_library_name}_LIBRARIES}) | ||
string(REGEX MATCH ${PYTHON_LIB_REGEX} _found ${entry}) | ||
if(_found STREQUAL "") | ||
list(APPEND REQ_STANDALONE_LIBS ${entry}) | ||
endif() | ||
endforeach() | ||
endmacro() | ||
|
||
# Install all libraries listed in REQ_STANDALONE_LIBS | ||
macro(install_standalone_dependencies) | ||
# Filter valid libraries | ||
list(FILTER REQ_STANDALONE_LIBS INCLUDE REGEX ".*(lib|dll|so)(\.[0-9])*$") | ||
list(REMOVE_DUPLICATES REQ_STANDALONE_LIBS) | ||
|
||
if(WIN32) | ||
foreach(lib_path ${REQ_STANDALONE_LIBS}) | ||
string(REGEX REPLACE "\/(l|L)ib\/" "/bin/" bin_path ${lib_path}) | ||
string(REGEX REPLACE "\.lib$" ".dll" dll_path ${bin_path}) | ||
list(APPEND REQ_STANDALONE_DLLS ${dll_path}) | ||
endforeach() | ||
install(FILES ${REQ_STANDALONE_DLLS} | ||
DESTINATION ros2_standalone | ||
) | ||
elseif(UNIX) | ||
set(_resolvedFiles "") | ||
foreach(lib_path ${REQ_STANDALONE_LIBS}) | ||
# Generate soversion files (.so.<major>). Some libs links to soversion symlinks which are not returned by find_package by default. | ||
get_filename_component(_resolvedFile "${lib_path}" REALPATH) | ||
list(APPEND _resolvedFiles "${_resolvedFile}") | ||
endforeach() | ||
install(FILES ${_resolvedFiles} | ||
DESTINATION ros2_standalone | ||
) | ||
|
||
# Fix soversion files | ||
foreach(_resolvedFile ${_resolvedFiles}) | ||
if("${_resolvedFile}" MATCHES "so(\.[0-9]+)+$") | ||
# Get file path without so | ||
string(FIND "${_resolvedFile}" ".so." _findPos) | ||
string(SUBSTRING "${_resolvedFile}" 0 ${_findPos} _cutted) | ||
|
||
set(_remainingPath "${_resolvedFile}") | ||
while("${_remainingPath}" MATCHES "so(\.[0-9]*)+$") | ||
string(FIND "${_remainingPath}" "." _lastDotPos REVERSE) | ||
string(SUBSTRING "${_remainingPath}" 0 ${_lastDotPos} _tempPos) | ||
get_filename_component(_libPathFilename "${_tempPos}" NAME) | ||
get_filename_component(_resolvedFilename "${_resolvedFile}" NAME) | ||
install(CODE "execute_process(COMMAND ln -s ${_resolvedFilename} ${_libPathFilename} WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX}/ros2_standalone ERROR_QUIET)") | ||
set(_remainingPath "${_tempPos}") | ||
endwhile() | ||
endif() | ||
endforeach() | ||
|
||
# rpath for each standalone lib must be updated so all the libs will see each other | ||
install(CODE | ||
"execute_process(COMMAND find ${CMAKE_INSTALL_PREFIX}/ros2_standalone -name *.so -exec patchelf --set-rpath $ORIGIN:. {} \;)" | ||
) | ||
# soversion files as well | ||
install(CODE | ||
"execute_process(COMMAND find ${CMAKE_INSTALL_PREFIX}/ros2_standalone -name *.so.* -exec patchelf --set-rpath $ORIGIN:. {} \;)" | ||
) | ||
endif() | ||
endmacro() | ||
|
||
# Libraries required by RGL | ||
set(ros2_standalone_libs | ||
rcl | ||
rclcpp | ||
sensor_msgs | ||
visualization_msgs | ||
rmw_implementation | ||
FastRTPS | ||
rmw_fastrtps_cpp | ||
CycloneDDS | ||
rmw_cyclonedds_cpp | ||
rmw_dds_common | ||
rosidl_runtime_c | ||
rosidl_typesupport_c | ||
rosidl_typesupport_cpp | ||
rosidl_typesupport_introspection_c | ||
rosidl_typesupport_introspection_cpp | ||
) | ||
|
||
foreach(ros2_standalone_lib ${ros2_standalone_libs}) | ||
get_standalone_dependencies(${ros2_standalone_lib}) | ||
endforeach() | ||
install_standalone_dependencies() |
Oops, something went wrong.