Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions .gitmodules

This file was deleted.

121 changes: 62 additions & 59 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,61 +1,64 @@
cmake_minimum_required(VERSION 3.11)
cmake_minimum_required(VERSION 3.16)
project(sas_core)

option(ROS2_BUILD "Enable ROS2/ament build (examples + ament integration)" ON)

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

# ---- Core libraries (always built) ----
include(cmake/cpplib.cmake)

if(ROS2_BUILD)
find_package(ament_cmake REQUIRED)
ament_python_install_package(${PROJECT_NAME})
set(_SAS_PYTHON_INSTALL_DIR "${PYTHON_INSTALL_DIR}/${PROJECT_NAME}")
endif()

include(cmake/pythonlib.cmake)

# ---- ROS2 / ament integration (conditional) ----
if(ROS2_BUILD)
# INTERFACE alias for downstream ROS packages
add_library(sas_core INTERFACE)
target_link_libraries(sas_core INTERFACE sas_core_pure)

ament_export_targets(export_${PROJECT_NAME} HAS_LIBRARY_TARGET)
ament_export_dependencies(Eigen3)

install(DIRECTORY include/ DESTINATION include)

install(TARGETS sas_core sas_core_pure
EXPORT export_${PROJECT_NAME}
ARCHIVE DESTINATION lib
INCLUDES DESTINATION include
)

# Example executables
foreach(_name IN ITEMS sas_core_example sas_clock_example
sas_clock_sched_fifo_example)
add_executable(${_name} src/examples/${_name}.cpp)
target_link_libraries(${_name} sas_core_pure)
if(_name STREQUAL "sas_core_example")
target_link_libraries(${_name} -ldqrobotics)
endif()
install(TARGETS ${_name} DESTINATION lib/${PROJECT_NAME})
endforeach()

add_executable(sas_robot_driver_example
src/examples/sas_robot_driver_example_main.cpp)
target_link_libraries(sas_robot_driver_example sas_core_pure)
install(TARGETS sas_robot_driver_example DESTINATION lib/${PROJECT_NAME})

install(DIRECTORY
scripts/
FILE_PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ
DESTINATION lib/${PROJECT_NAME}
)

ament_package()
endif()
# =============================================================================
# sas_core is a THIN WRAPPER around the SmartArmStack core:
#
# - C++ library: libmarinholab_sas_core, provided by the
# libmarinholab-sas-core .deb (source: https://github.com/MarinhoLab/sas_cpp).
# The .deb installs headers under include/marinholab/sas/core/, the shared
# library, and the CMake package config (find_package(marinholab_sas_core)).
# - Python bindings: the PyPI package marinholab-sas-core
# (https://github.com/MarinhoLab/sas_py), imported as marinholab.sas.core.
#
# This package adds no implementation; it only:
# 1. re-exports the ament target `sas_core` so downstream ROS packages keep
# working with `ament_target_dependencies(<pkg> sas_core ...)`;
# 2. installs compatibility headers include/sas_core/*.hpp that forward to
# the .deb's include/marinholab/sas/core/*.hpp and re-alias `namespace sas`;
# 3. installs the pure-Python `sas_core` shim (re-exporting
# marinholab.sas.core) so `from sas_core import Clock` keeps working.
# =============================================================================

find_package(marinholab_sas_core REQUIRED)
find_package(ament_cmake REQUIRED)
find_package(ament_cmake_python REQUIRED)

# Eigen3 is a PUBLIC dependency of the core (its headers include <Eigen/Dense>);
# declare it so downstream ament packages can resolve it through this package.
find_package(Eigen3 REQUIRED)

# ---- ament target ---------------------------------------------------------
# INTERFACE alias forwarding downstream packages to the core target installed
# by the libmarinholab-sas-core .deb.
add_library(sas_core INTERFACE)
target_link_libraries(sas_core INTERFACE marinholab::sas::core Eigen3::Eigen)

ament_export_targets(export_${PROJECT_NAME} HAS_LIBRARY_TARGET)
# Eigen3 and marinholab_sas_core are consumed transitively by downstream
# packages that link the `sas_core` target; propagate them so their
# find_package() calls run in the consumer.
ament_export_dependencies(Eigen3 marinholab_sas_core)

# ---- Compatibility headers ------------------------------------------------
# include/sas_core/*.hpp are thin shims forwarding to the .deb's
# include/marinholab/sas/core/*.hpp and re-aliasing `namespace sas`.
install(DIRECTORY include/ DESTINATION include)

install(TARGETS sas_core
EXPORT export_${PROJECT_NAME}
)

# ---- Python compatibility shim ---------------------------------------------
# Pure-Python module re-exporting marinholab.sas.core (installed from PyPI by
# the docker environment / user). See sas_core/__init__.py.
ament_python_install_package(${PROJECT_NAME})

# Example scripts (run against the PyPI-installed bindings).
install(
DIRECTORY scripts/
FILE_PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ
DESTINATION lib/${PROJECT_NAME}
)

ament_package()
94 changes: 58 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,59 +1,81 @@
# sas_core
# sas_core (thin wrapper)

> [!TIP]
> Repository for this module: https://github.com/SmartArmStack/sas_core. <br/>
> More information about SmartArmStack is available in https://smartarmstack.github.io/.

## Contents

- `include/sas_core/` — public C++ headers.
- `src/` — implementation of the shared library and pybind11 bindings.
- `scripts/` — example Python scripts.
- `src/examples/` — C++ example programs and test nodes.
`sas_core` is a **thin ROS 2 wrapper** around the SmartArmStack core. It
contains no C++ implementation and no Python extension module of its own; it
forwards to the two packages that provide the core:

## Using as a non-ROS2 dependency (CMake FetchContent)
| Piece | Provided by | Installed as |
|---|---|---|
| C++ library (`libmarinholab_sas_core`) + headers + CMake config | [MarinhoLab/sas_cpp](https://github.com/MarinhoLab/sas_cpp) | `libmarinholab-sas-core` `.deb` (target namespace `marinholab::sas::core`) |
| Python bindings | [MarinhoLab/sas_py](https://github.com/MarinhoLab/sas_py) | `marinholab-sas-core` on PyPI (import `marinholab.sas.core`) |

To include `sas_core_pure` in a plain CMake project (no ROS2/ament required):
On Ubuntu the `.deb` links the dynamic `libdqrobotics` from the
[dqrobotics PPA](https://launchpad.net/~dqrobotics-dev/+archive/ubuntu/development);
in the provided docker environment both are already installed.

```cmake
include(FetchContent)
FetchContent_Declare(
sas_core
GIT_REPOSITORY https://github.com/SmartArmStack/sas_core.git
GIT_TAG jazzy
)
## What this package provides

set(ROS2_BUILD OFF CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(sas_core)

target_link_libraries(your_target PRIVATE sas_core_pure)
```
- **C++**: the ament target `sas_core` (`ament_target_dependencies(<pkg> sas_core ...)`)
forwarding to `marinholab::sas::core`, plus **compatibility headers**
`include/sas_core/*.hpp` that keep the legacy include paths
(`#include <sas_core/sas_clock.hpp>`) and the legacy `namespace sas` working
via `#include <marinholab/sas/core/...>` + a namespace alias.
- **Python**: a pure-Python `sas_core` shim that re-exports
`Clock`, `Statistics`, `RobotDriver`, `ShutdownSignaler` from
`marinholab.sas.core`, so `from sas_core import Clock` keeps working.

The library depends on **Eigen3** and **dqrobotics**; make sure both are
available on your system.
## Contents

## Examples
- `include/sas_core/` — compatibility C++ headers (one-line forwards).
- `sas_core/__init__.py` — Python compatibility shim.
- `scripts/` — example Python scripts + `sas_core_smoke_test.py`.
- `docker/` — build environment and integration smoke test.

Testing on a docker container.
## Installation

```bash
docker run --rm murilomarinho/sas:jazzy bash -c "ros2 run sas_core sas_clock_example"
# C++ core (until the .deb is published to an apt repository, build it from source):
sudo add-apt-repository ppa:dqrobotics-dev/development
sudo apt-get update
sudo apt-get install -y libdqrobotics
# then build sas_cpp with dpkg-buildpackage and dpkg -i the result,
# or simply: sudo apt-get install libmarinholab-sas-core (once published)

# Python bindings:
python3 -m pip install marinholab-sas-core

# This wrapper (inside a ROS 2 workspace):
colcon build
```

```bash
ros2 run sas_core sas_core_example
ros2 run sas_core sas_clock_example
ros2 run sas_core sas_clock_sched_fifo_example
ros2 run sas_core sas_robot_driver_example
```
## Examples

The C++ example programs live with the C++ core
([MarinhoLab/sas_cpp](https://github.com/MarinhoLab/sas_cpp), built with
`-DMARINHO_LAB_SAS_CORE_BUILD_EXAMPLES=ON`). The Python examples in
`scripts/` run against the PyPI-installed bindings:

```bash
ros2 run sas_core sas_clock_example_py.py
ros2 run sas_core sas_robot_driver_subclass_example_py.py
ros2 run sas_core sas_clock_sched_fifo_example_py.py
ros2 run sas_core sas_robot_driver_subclass_example_py.py
```

The `scripts/sas_robot_driver_subclass_example_py.py` file demonstrates how to
subclass `sas_core.RobotDriver` in Python and contains a minimal working
example.
`sas_robot_driver_subclass_example_py.py` demonstrates subclassing
`sas_core.RobotDriver` in Python.

## Testing

The docker environment builds the wrapper with `colcon` and runs a smoke test
covering both consumption paths (Python shim + C++ compatibility headers
against the installed library):

```bash
cd docker
docker compose build
docker compose up
```
25 changes: 0 additions & 25 deletions cmake/cpplib.cmake

This file was deleted.

27 changes: 0 additions & 27 deletions cmake/pythonlib.cmake

This file was deleted.

30 changes: 27 additions & 3 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,31 @@ SHELL ["/bin/bash", "-c"]
ENV BASH_ENV="/etc/bash_env"

RUN sudo apt-get update && sudo apt-get upgrade -y
RUN python3 -m pip install --upgrade dqrobotics --break-system-packages
RUN sudo sudo apt-get remove -y ros-jazzy-sas-core

# Remove the legacy monolithic sas_core package shipped by the base image;
# it would otherwise shadow this thin wrapper.
RUN sudo apt-get remove -y ros-jazzy-sas-core

# Python bindings from PyPI (self-contained wheel, core statically linked).
# dqrobotics (python) is already present in the base image.
RUN python3 -m pip install --upgrade marinholab-sas-core --break-system-packages

# C++ core .deb -- TEMPORARY: built from source because the
# libmarinholab-sas-core .deb is not yet published to an apt repository.
# libdqrobotics (C++) is already present in the base image, so no PPA is
# needed here. The build is architecture-agnostic (amd64 or arm64).
#
# Once the .deb is published to an apt repository, replace this block with:
# RUN sudo apt-get update \
# && sudo apt-get install -y libmarinholab-sas-core
RUN sudo apt-get update \
&& sudo apt-get install -y debhelper dpkg-dev \
&& git clone --depth 1 --branch 26.09 https://github.com/MarinhoLab/sas_cpp.git /tmp/sas_cpp \
&& cd /tmp/sas_cpp \
&& dpkg-buildpackage -us -uc -b \
&& cd /tmp \
&& sudo dpkg -i ./libmarinholab-sas-core_*.deb \
&& sudo rm -rf /tmp/sas_cpp /tmp/libmarinholab-sas-core_*.deb

RUN mkdir -p /root/sas_core_devel/src/
COPY . /root/sas_core_devel/src/sas_core
COPY . /root/sas_core_devel/src/sas_core
13 changes: 1 addition & 12 deletions docker/compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,4 @@ services:
dockerfile: docker/Dockerfile
environment:
PYTHONUNBUFFERED: 1
command: /bin/bash -c "
cd /root/sas_core_devel/src/
&& ls .
&& colcon build
&& source install/setup.bash
&& ros2 run sas_core sas_clock_example
&& ros2 run sas_core sas_clock_example_py.py
&& ros2 run sas_core sas_robot_driver_example
&& ros2 run sas_core sas_robot_driver_subclass_example_py.py
&& ros2 run sas_core sas_clock_sched_fifo_example
&& ros2 run sas_core sas_clock_sched_fifo_example_py.py
"
command: /bin/bash -c "bash /root/sas_core_devel/src/sas_core/docker/smoke_test.sh"
Loading
Loading