From 43c01931d9642633467886b3b13276922d4fec45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20J=C3=BClg?= Date: Sat, 29 Nov 2025 10:53:48 +0100 Subject: [PATCH 01/16] docs: no build isolation in pip --- README.md | 2 +- docs/getting_started/index.md | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 213cbfa3..8332188c 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ We build and test RCS on the latest Debian and on the latest Ubuntu LTS. 3. **Install RCS**: ```shell - pip install -ve . + pip install -ve . --no-build-isolation ``` ## Hardware Extensions diff --git a/docs/getting_started/index.md b/docs/getting_started/index.md index 8ac559a0..35c2f9ec 100644 --- a/docs/getting_started/index.md +++ b/docs/getting_started/index.md @@ -23,7 +23,6 @@ We build and test RCS on the latest Debian and on the latest Ubuntu LTS. ```shell pip install -r requirements_dev.txt - pip config --site set global.no-build-isolation false ``` ### Building RCS @@ -31,7 +30,7 @@ We build and test RCS on the latest Debian and on the latest Ubuntu LTS. Build and install RCS in editable mode: ```shell -pip install -ve . +pip install -ve . --no-build-isolation ``` For a docker deployment, see the `docker` folder in the repository. From a89c70c9ed6a5a43a0e48b663c3e4ae027975e55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20J=C3=BClg?= Date: Sat, 29 Nov 2025 12:41:45 +0100 Subject: [PATCH 02/16] build: moved dev deps into pyproject - moved development dependencies into pyproject.toml installable via ;.[dev]' - moved robotics library debian dependencies into the extension - fixed and clarified readme and documentation install instructions --- README.md | 8 +++--- debian_deps.txt | 14 +--------- docs/contributing/index.md | 12 +++++---- docs/extensions/rcs_fr3.md | 3 ++- docs/extensions/rcs_panda.md | 3 ++- docs/extensions/rcs_robotics_library.md | 2 ++ docs/getting_started/index.md | 8 +++--- extensions/rcs_fr3/README.md | 3 ++- extensions/rcs_panda/README.md | 3 ++- extensions/rcs_robotics_library/README.md | 4 ++- .../rcs_robotics_library/debian_deps.txt | 7 +++++ pyproject.toml | 26 ++++++++++++------- requirements.txt | 8 ++++++ requirements_dev.txt | 18 ------------- 14 files changed, 61 insertions(+), 58 deletions(-) create mode 100644 extensions/rcs_robotics_library/debian_deps.txt create mode 100644 requirements.txt delete mode 100644 requirements_dev.txt diff --git a/README.md b/README.md index 8332188c..33ab7405 100644 --- a/README.md +++ b/README.md @@ -13,9 +13,9 @@ We build and test RCS on the latest Debian and on the latest Ubuntu LTS. 2. **Python Environment**: ```shell - python3 -m venv .venv - source .venv/bin/activate - pip install -r requirements_dev.txt + conda create -n rcs python=3.11 + conda activate rcs + pip install -r requirements.txt ``` 3. **Install RCS**: @@ -30,7 +30,7 @@ RCS supports various hardware extensions (e.g., FR3, xArm7, RealSense). These ar To install an extension: ```shell -pip install -ve extensions/rcs_fr3 +pip install -ve extensions/rcs_fr3 --no-build-isolation ``` For a full list of extensions and detailed documentation, visit [robotcontrolstack.org/extensions](https://robotcontrolstack.org/extensions). diff --git a/debian_deps.txt b/debian_deps.txt index 2eb7ba2d..58e188ca 100644 --- a/debian_deps.txt +++ b/debian_deps.txt @@ -1,17 +1,5 @@ build-essential -cmake -git +gcc libpoco-dev libeigen3-dev -libxslt-dev -libcoin-dev -libccd-dev libglfw3-dev -libboost-all-dev -liblzma-dev -libxml2-dev -libxslt1-dev -ninja-build -clang -clang-format -clang-tidy diff --git a/docs/contributing/index.md b/docs/contributing/index.md index 5c493844..c1b0c8f7 100644 --- a/docs/contributing/index.md +++ b/docs/contributing/index.md @@ -6,13 +6,15 @@ We welcome contributions to the Robot Control Stack! 1. Clone the repository. 2. Install dependencies (see [Getting Started](../getting_started/index.md)). -3. Install pre-commit hooks: - ```shell - pre-commit install - ``` ## Development Tools +Install the development dependencies: +```shell +# from root directory +pip install -ve '.[dev]' --no-build-isolation +``` + We provide a `Makefile` with several useful commands for development. ### Python @@ -96,7 +98,7 @@ See [conventionalcommits.org](https://www.conventionalcommits.org/) for more det ## Pull Requests -1. Create a new branch for your feature or fix. +1. Fork the repo and create a new branch for your feature or fix. 2. Make your changes and commit them using the conventional commit format. 3. Push your branch and open a Pull Request. 4. Ensure all CI checks pass. diff --git a/docs/extensions/rcs_fr3.md b/docs/extensions/rcs_fr3.md index ee501e39..7c1cddf4 100644 --- a/docs/extensions/rcs_fr3.md +++ b/docs/extensions/rcs_fr3.md @@ -5,7 +5,8 @@ This extension provides support for the Franka Research 3 (FR3) robot in RCS. ## Installation ```shell -pip install -ve extensions/rcs_fr3 +# from root directory +pip install -ve extensions/rcs_fr3 --no-build-isolation ``` ### Configuration diff --git a/docs/extensions/rcs_panda.md b/docs/extensions/rcs_panda.md index 10846fe9..763a46e9 100644 --- a/docs/extensions/rcs_panda.md +++ b/docs/extensions/rcs_panda.md @@ -5,7 +5,8 @@ This extension provides support for the Franka Emika Panda robot in RCS. ## Installation ```shell -pip install -ve extensions/rcs_panda +# from root directory +pip install -ve extensions/rcs_panda --no-build-isolation ``` ## Usage diff --git a/docs/extensions/rcs_robotics_library.md b/docs/extensions/rcs_robotics_library.md index d7cf7a87..2c6893e8 100644 --- a/docs/extensions/rcs_robotics_library.md +++ b/docs/extensions/rcs_robotics_library.md @@ -5,5 +5,7 @@ This extension provides integration with the [Robotics Library (RL)](https://www ## Installation ```shell +# from root directory +sudo apt install $(cat extensions/rcs_robotics_library/debian_deps.txt) pip install -ve extensions/rcs_robotics_library ``` diff --git a/docs/getting_started/index.md b/docs/getting_started/index.md index 35c2f9ec..25f560d1 100644 --- a/docs/getting_started/index.md +++ b/docs/getting_started/index.md @@ -12,17 +12,17 @@ We build and test RCS on the latest Debian and on the latest Ubuntu LTS. sudo apt install $(cat debian_deps.txt) ``` -2. Create, activate and configure a [Python virtual environment](https://docs.python.org/3/library/venv.html): +2. Create and activate Python virtual environment or conda environment: ```shell - python3 -m venv .venv - source .venv/bin/activate + conda create -n rcs python=3.11 + conda activate rcs ``` 3. Install the package dependencies: ```shell - pip install -r requirements_dev.txt + pip install -r requirements.txt ``` ### Building RCS diff --git a/extensions/rcs_fr3/README.md b/extensions/rcs_fr3/README.md index 87157711..ac4b7185 100644 --- a/extensions/rcs_fr3/README.md +++ b/extensions/rcs_fr3/README.md @@ -3,7 +3,8 @@ Extension to control the fr3 with rcs. ## Installation ```shell -pip install -ve . +# go to this directory +pip install -ve . --no-build-isolation ``` Add your FR3 credentials to a `.env` file like this: diff --git a/extensions/rcs_panda/README.md b/extensions/rcs_panda/README.md index 7e32430d..ea9f474a 100644 --- a/extensions/rcs_panda/README.md +++ b/extensions/rcs_panda/README.md @@ -3,7 +3,8 @@ Extension to control the panda with rcs. ## Installation ```shell -pip install -ve . +# go to this directory +pip install -ve . --no-build-isolation ``` Add your Panda credentials to a `.env` file like this: diff --git a/extensions/rcs_robotics_library/README.md b/extensions/rcs_robotics_library/README.md index 54fd79e7..67d4c7fc 100644 --- a/extensions/rcs_robotics_library/README.md +++ b/extensions/rcs_robotics_library/README.md @@ -3,7 +3,9 @@ Implements access to the C++ library "Robotics Library". ## Installation ```shell -pip install -ve . +# go to this directory +sudo apt install $(cat debian_deps.txt) +pip install -ve . --no-build-isolation ``` ## Usage diff --git a/extensions/rcs_robotics_library/debian_deps.txt b/extensions/rcs_robotics_library/debian_deps.txt new file mode 100644 index 00000000..86b54136 --- /dev/null +++ b/extensions/rcs_robotics_library/debian_deps.txt @@ -0,0 +1,7 @@ +libxslt-dev +libcoin-dev +libccd-dev +libboost-all-dev +liblzma-dev +libxml2-dev +libxslt1-dev \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 9fc9c1bf..8163ed2f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,6 +25,7 @@ dependencies = ["websockets>=11.0", "pin==3.7.0", "tilburg-hand", "digit-interface", + "pyopengl>=3.1.9", "ompl>=1.7.0", "rpyc==6.0.2", ] @@ -39,15 +40,22 @@ authors = [ requires-python = ">=3.10" license = "AGPL-3.0-or-later" -# until https://github.com/pypa/pip/issues/11440 is resolved -# we use requirements_dev.txt for linter and formatter dependencies -# [project.optional-dependencies] -# dev = [ -# "ruff==0.3.2", -# "black==24.1.1", -# "isort==5.13.2", -# "mypy==1.4.1", -# ] +[project.optional-dependencies] +dev = [ + "ruff==0.3.2", + "black==24.1.1", + "isort==5.13.2", + "mypy==1.10.1", + "types-requests~=2.31", + # temporarily use fixed version until PR #275 is merged + # pybind11-stubgen==2.5.5 + "pybind11-stubgen @ git+https://github.com/juelg/pybind11-stubgen@fix/class-sorting", + "pytest==8.1.1", + "commitizen~=3.28.0", + "clang", + "clang-format", + "clang-tidy", +] [tool.scikit-build] diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..7474dbd7 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,8 @@ +build +wheel +scikit-build-core>=0.3.3 +pybind11 +cmake +ninja +mujoco==3.2.6 +pin==3.7.0 \ No newline at end of file diff --git a/requirements_dev.txt b/requirements_dev.txt deleted file mode 100644 index f905b2f9..00000000 --- a/requirements_dev.txt +++ /dev/null @@ -1,18 +0,0 @@ -ruff==0.3.2 -black==24.1.1 -isort==5.13.2 -mypy==1.10.1 -pyopengl==3.1.9 -types-requests~=2.31 -# temporarily use fixed version until PR #275 is merged -# pybind11-stubgen==2.5.5 -pybind11-stubgen @ git+https://github.com/juelg/pybind11-stubgen@fix/class-sorting -build -pytest==8.1.1 -commitizen~=3.28.0 -scikit-build-core>=0.3.3 -poetry-core>=2.1.3 -pybind11 -mujoco==3.2.6 -pin==3.7.0 -wheel From a25127940dcc7e7afc0ddf53ee1ac4b6b53d609d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20J=C3=BClg?= Date: Sun, 30 Nov 2025 17:05:26 +0100 Subject: [PATCH 03/16] chore: cleanup of old files and make format fix --- .ci_docker/Dockerfile | 17 -- .ci_docker/script.deb.sh | 221 ------------------ .github/workflows/cpp.yaml | 2 +- .gitlab-ci.yml | 47 ---- Makefile | 2 - extensions/rcs_fr3/pyproject.toml | 13 +- extensions/rcs_panda/pyproject.toml | 18 +- extensions/rcs_realsense/pyproject.toml | 11 +- .../rcs_robotics_library/pyproject.toml | 10 +- extensions/rcs_so101/pyproject.toml | 11 +- extensions/rcs_tacto/pyproject.toml | 12 +- extensions/rcs_usb_cam/pyproject.toml | 13 +- extensions/rcs_xarm7/pyproject.toml | 8 +- 13 files changed, 63 insertions(+), 322 deletions(-) delete mode 100644 .ci_docker/Dockerfile delete mode 100755 .ci_docker/script.deb.sh delete mode 100644 .gitlab-ci.yml diff --git a/.ci_docker/Dockerfile b/.ci_docker/Dockerfile deleted file mode 100644 index 814c8913..00000000 --- a/.ci_docker/Dockerfile +++ /dev/null @@ -1,17 +0,0 @@ -# syntax=docker/dockerfile:1 -FROM ubuntu:latest - -# dependencies for our repo -RUN apt-get update && apt-get install --yes build-essential cmake git libpoco-dev libeigen3-dev libxslt-dev libcoin-dev libccd-dev libglfw3-dev libboost-all-dev liblzma-dev ninja-build clang python-is-python3 python3-venv python3-pip -# dependencies for linting -RUN apt-get update && apt-get install --yes clang-tidy clang-format - -# dependencies for gitlab-runner -WORKDIR /rcs -COPY script.deb.sh . -RUN ./script.deb.sh -RUN rm ./script.deb.sh -RUN apt-get install --yes gitlab-runner -ARG TOKEN -RUN gitlab-runner register --url https://gitos.rrze.fau.de --non-interactive --executor shell --token ${TOKEN} -CMD gitlab-runner run diff --git a/.ci_docker/script.deb.sh b/.ci_docker/script.deb.sh deleted file mode 100755 index 298cb9ee..00000000 --- a/.ci_docker/script.deb.sh +++ /dev/null @@ -1,221 +0,0 @@ -#!/bin/bash - -unknown_os () -{ - echo "Unfortunately, your operating system distribution and version are not supported by this script." - echo - echo "You can override the OS detection by setting os= and dist= prior to running this script." - echo "You can find a list of supported OSes and distributions on our website: https://packages.gitlab.com/docs#os_distro_version" - echo - echo "For example, to force Ubuntu Trusty: os=ubuntu dist=trusty ./script.sh" - echo - echo "Please email support@packagecloud.io and let us know if you run into any issues." - exit 1 -} - -gpg_check () -{ - echo "Checking for gpg..." - if command -v gpg > /dev/null; then - echo "Detected gpg..." - else - echo "Installing gnupg for GPG verification..." - apt-get install -y gnupg - if [ "$?" -ne "0" ]; then - echo "Unable to install GPG! Your base system has a problem; please check your default OS's package repositories because GPG should work." - echo "Repository installation aborted." - exit 1 - fi - fi -} - -curl_check () -{ - echo "Checking for curl..." - if command -v curl > /dev/null; then - echo "Detected curl..." - else - echo "Installing curl..." - apt-get install -q -y curl - if [ "$?" -ne "0" ]; then - echo "Unable to install curl! Your base system has a problem; please check your default OS's package repositories because curl should work." - echo "Repository installation aborted." - exit 1 - fi - fi -} - -install_debian_keyring () -{ - if [ "${os,,}" = "debian" ]; then - echo "Installing debian-archive-keyring which is needed for installing " - echo "apt-transport-https on many Debian systems." - apt-get install -y debian-archive-keyring &> /dev/null - fi -} - - -detect_os () -{ - if [[ ( -z "${os}" ) && ( -z "${dist}" ) ]]; then - # some systems dont have lsb-release yet have the lsb_release binary and - # vice-versa - if [ -e /etc/lsb-release ]; then - . /etc/lsb-release - - if [ "${ID}" = "raspbian" ]; then - os=${ID} - dist=`cut --delimiter='.' -f1 /etc/debian_version` - else - os=${DISTRIB_ID} - dist=${DISTRIB_CODENAME} - - if [ -z "$dist" ]; then - dist=${DISTRIB_RELEASE} - fi - fi - - elif [ `which lsb_release 2>/dev/null` ]; then - dist=`lsb_release -c | cut -f2` - os=`lsb_release -i | cut -f2 | awk '{ print tolower($1) }'` - - elif [ -e /etc/debian_version ]; then - # some Debians have jessie/sid in their /etc/debian_version - # while others have '6.0.7' - os=`cat /etc/issue | head -1 | awk '{ print tolower($1) }'` - if grep -q '/' /etc/debian_version; then - dist=`cut --delimiter='/' -f1 /etc/debian_version` - else - dist=`cut --delimiter='.' -f1 /etc/debian_version` - fi - - else - unknown_os - fi - fi - - if [ -z "$dist" ]; then - unknown_os - fi - - # remove whitespace from OS and dist name - os="${os// /}" - dist="${dist// /}" - - echo "Detected operating system as $os/$dist." -} - -detect_version_id () { - # detect version_id and round down float to integer - if [ -f /etc/os-release ]; then - . /etc/os-release - version_id=${VERSION_ID%%.*} - elif [ -f /usr/lib/os-release ]; then - . /usr/lib/os-release - version_id=${VERSION_ID%%.*} - else - version_id="1" - fi -} - -main () -{ - detect_os - curl_check - gpg_check - detect_version_id - - # Need to first run apt-get update so that apt-transport-https can be - # installed - echo -n "Running apt-get update... " - apt-get update &> /dev/null - echo "done." - - # Install the debian-archive-keyring package on debian systems so that - # apt-transport-https can be installed next - install_debian_keyring - - echo -n "Installing apt-transport-https... " - apt-get install -y apt-transport-https &> /dev/null - echo "done." - - - gpg_key_url="https://packages.gitlab.com/runner/gitlab-runner/gpgkey" - apt_config_url="https://packages.gitlab.com/install/repositories/runner/gitlab-runner/config_file.list?os=${os}&dist=${dist}&source=script" - - apt_source_path="/etc/apt/sources.list.d/runner_gitlab-runner.list" - gpg_keyring_path="/usr/share/keyrings/runner_gitlab-runner-archive-keyring.gpg" - - echo -n "Installing $apt_source_path..." - - # create an apt config file for this repository - curl -sSf "${apt_config_url}" > $apt_source_path - curl_exit_code=$? - - if [ "$curl_exit_code" = "22" ]; then - echo - echo - echo -n "Unable to download repo config from: " - echo "${apt_config_url}" - echo - echo "This usually happens if your operating system is not supported by " - echo "packagecloud.io, or this script's OS detection failed." - echo - echo "You can override the OS detection by setting os= and dist= prior to running this script." - echo "You can find a list of supported OSes and distributions on our website: https://packages.gitlab.com/docs#os_distro_version" - echo - echo "For example, to force Ubuntu Trusty: os=ubuntu dist=trusty ./script.sh" - echo - echo "If you are running a supported OS, please email support@packagecloud.io and report this." - [ -e $apt_source_path ] && rm $apt_source_path - exit 1 - elif [ "$curl_exit_code" = "35" -o "$curl_exit_code" = "60" ]; then - echo "curl is unable to connect to packagecloud.io over TLS when running: " - echo " curl ${apt_config_url}" - echo "This is usually due to one of two things:" - echo - echo " 1.) Missing CA root certificates (make sure the ca-certificates package is installed)" - echo " 2.) An old version of libssl. Try upgrading libssl on your system to a more recent version" - echo - echo "Contact support@packagecloud.io with information about your system for help." - [ -e $apt_source_path ] && rm $apt_source_path - exit 1 - elif [ "$curl_exit_code" -gt "0" ]; then - echo - echo "Unable to run: " - echo " curl ${apt_config_url}" - echo - echo "Double check your curl installation and try again." - [ -e $apt_source_path ] && rm $apt_source_path - exit 1 - else - echo "done." - fi - - echo -n "Importing packagecloud gpg key... " - # import the gpg key - curl -fsSL "${gpg_key_url}" | gpg --dearmor > ${gpg_keyring_path} - # check for os/dist based on pre debian stretch - if - { [ "${os,,}" = "debian" ] && [ "${version_id}" -lt 9 ]; } || - { [ "${os,,}" = "ubuntu" ] && [ "${version_id}" -lt 16 ]; } || - { [ "${os,,}" = "linuxmint" ] && [ "${version_id}" -lt 19 ]; } || - { [ "${os,,}" = "raspbian" ] && [ "${version_id}" -lt 9 ]; } || - { { [ "${os,,}" = "elementaryos" ] || [ "${os,,}" = "elementary" ]; } && [ "${version_id}" -lt 5 ]; } - then - # move to trusted.gpg.d - mv ${gpg_keyring_path} /etc/apt/trusted.gpg.d/runner_gitlab-runner.gpg - fi - echo "done." - - echo -n "Running apt-get update... " - # update apt on this system - apt-get update &> /dev/null - echo "done." - - echo - echo "The repository is setup! You can now install packages." -} - -main - diff --git a/.github/workflows/cpp.yaml b/.github/workflows/cpp.yaml index 5bd68580..525d694c 100644 --- a/.github/workflows/cpp.yaml +++ b/.github/workflows/cpp.yaml @@ -27,7 +27,7 @@ jobs: - name: Clang build run: make clangcompile PYTHON_EXECUTABLE=${{ steps.setup-python.outputs.python-path }} - name: Clang Tidy - run: clang-tidy -p=build --warnings-as-errors='*' $(find src -name '*.cpp' -o -name '*.cc' -name '*.h') + run: make cpplint build_gcc: runs-on: ubuntu-latest diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index 5f05ab91..00000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,47 +0,0 @@ -stages: - - cpp - - python_pre_install - - python - - python_post_install - -cpp_format: - stage: cpp - script: - - make cppcheckformat - -gcc_compile: - stage: cpp - script: - - make gcccompile - -clang_compile: - stage: cpp - script: - - make clangcompile - - make cpplint - -python_dependencies: - stage: python_pre_install - script: - - pip3 install --break-system-packages -r requirements_dev.txt - -python_format: - stage: python - script: - - make pycheckformat - -python_lint: - stage: python - script: - - make pylint - -python_build: - stage: python - script: - - pip3 install --break-system-packages . - - make stubgen && git diff --exit-code - -python_unittest: - stage: python_post_install - script: - - make pytest diff --git a/Makefile b/Makefile index 516c09c1..a1d1e0d2 100644 --- a/Makefile +++ b/Makefile @@ -5,11 +5,9 @@ COMPILE_MODE = Release # CPP cppcheckformat: clang-format --dry-run -Werror -i $(shell find ${CPPSRC} -name '*.cpp' -o -name '*.cc' -o -name '*.h') - clang-format --dry-run -Werror -i $(shell find extensions/rcs_fr3/src -name '*.cpp' -o -name '*.cc' -o -name '*.h') cppformat: clang-format -Werror -i $(shell find ${CPPSRC} -name '*.cpp' -o -name '*.cc' -o -name '*.h') - clang-format -Werror -i $(shell find extensions/rcs_fr3/src -name '*.cpp' -o -name '*.cc' -o -name '*.h') cpplint: clang-tidy -p=build --warnings-as-errors='*' $(shell find ${CPPSRC} -name '*.cpp' -o -name '*.cc' -name '*.h') diff --git a/extensions/rcs_fr3/pyproject.toml b/extensions/rcs_fr3/pyproject.toml index 6061cd53..977531cb 100644 --- a/extensions/rcs_fr3/pyproject.toml +++ b/extensions/rcs_fr3/pyproject.toml @@ -9,16 +9,14 @@ description="RCS libfranka integration" dependencies = [ "rcs>=0.5.0", ] -readme = "../../README.md" +readme = "README.md" maintainers = [ { name = "Tobias Jülg", email = "tobias.juelg@utn.de" }, ] authors = [ { name = "Tobias Jülg", email = "tobias.juelg@utn.de" }, - { name = "Pierre Krack", email = "pierre.krack@utn.de" }, ] requires-python = ">=3.10" -license = "AGPL-3.0-or-later" [tool.scikit-build] @@ -27,4 +25,11 @@ build.targets = ["_core"] logging.level = "INFO" build-dir = "build" wheel.packages = ["src/rcs_fr3"] -install.components = ["python_package"] \ No newline at end of file +install.components = ["python_package"] + +[tool.black] +line-length = 120 +target-version = ["py311"] + +[tool.isort] +profile = "black" \ No newline at end of file diff --git a/extensions/rcs_panda/pyproject.toml b/extensions/rcs_panda/pyproject.toml index 8d67d83a..8d741532 100644 --- a/extensions/rcs_panda/pyproject.toml +++ b/extensions/rcs_panda/pyproject.toml @@ -9,21 +9,14 @@ description="RCS libfranka integration" dependencies = [ "rcs>=0.5.0", ] -readme = "../../README.md" +readme = "README.md" maintainers = [ { name = "Tobias Jülg", email = "tobias.juelg@utn.de" }, ] authors = [ { name = "Tobias Jülg", email = "tobias.juelg@utn.de" }, - { name = "Pierre Krack", email = "pierre.krack@utn.de" }, ] requires-python = ">=3.10" -license = {file = "../../LICENSE"} -classifiers = [ - "Development Status :: 3 - Alpha", - "License :: OSI Approved :: GNU Affero General Public License v3 (AGPLv3)", - "Programming Language :: Python :: 3", -] [tool.scikit-build] @@ -32,4 +25,11 @@ build.targets = ["_core"] logging.level = "INFO" build-dir = "build" wheel.packages = ["src/rcs_panda"] -install.components = ["python_package"] \ No newline at end of file +install.components = ["python_package"] + +[tool.black] +line-length = 120 +target-version = ["py311"] + +[tool.isort] +profile = "black" \ No newline at end of file diff --git a/extensions/rcs_realsense/pyproject.toml b/extensions/rcs_realsense/pyproject.toml index d0917ae8..709e5159 100644 --- a/extensions/rcs_realsense/pyproject.toml +++ b/extensions/rcs_realsense/pyproject.toml @@ -12,14 +12,17 @@ dependencies = [ "apriltag==0.0.16", "diskcache", ] -readme = "README.md" maintainers = [ { name = "Tobias Jülg", email = "tobias.juelg@utn.de" }, ] authors = [ { name = "Tobias Jülg", email = "tobias.juelg@utn.de" }, - { name = "Pierre Krack", email = "pierre.krack@utn.de" }, ] -requires-python = ">=3.10" -license = "AGPL-3.0-or-later" +requires-python = ">=3.11" +[tool.black] +line-length = 120 +target-version = ["py311"] + +[tool.isort] +profile = "black" diff --git a/extensions/rcs_robotics_library/pyproject.toml b/extensions/rcs_robotics_library/pyproject.toml index 01f37780..051757a2 100644 --- a/extensions/rcs_robotics_library/pyproject.toml +++ b/extensions/rcs_robotics_library/pyproject.toml @@ -18,7 +18,6 @@ authors = [ { name = "Pierre Krack", email = "pierre.krack@utn.de" }, ] requires-python = ">=3.10" -license = "AGPL-3.0-or-later" [tool.scikit-build] @@ -27,4 +26,11 @@ build.targets = ["_core"] logging.level = "INFO" build-dir = "build" wheel.packages = ["src/rcs_robotics_library"] -install.components = ["python_package"] \ No newline at end of file +install.components = ["python_package"] + +[tool.black] +line-length = 120 +target-version = ["py311"] + +[tool.isort] +profile = "black" \ No newline at end of file diff --git a/extensions/rcs_so101/pyproject.toml b/extensions/rcs_so101/pyproject.toml index c390d01a..78bb8c35 100644 --- a/extensions/rcs_so101/pyproject.toml +++ b/extensions/rcs_so101/pyproject.toml @@ -16,10 +16,8 @@ maintainers = [ ] authors = [ { name = "Tobias Jülg", email = "tobias.juelg@utn.de" }, - { name = "Pierre Krack", email = "pierre.krack@utn.de" }, ] requires-python = ">=3.10" -license = "AGPL-3.0-or-later" [tool.scikit-build] build.verbose = true @@ -27,4 +25,11 @@ build.targets = ["_core"] logging.level = "INFO" build-dir = "build" wheel.packages = ["src/rcs_so101"] -install.components = ["python_package"] \ No newline at end of file +install.components = ["python_package"] + +[tool.black] +line-length = 120 +target-version = ["py311"] + +[tool.isort] +profile = "black" \ No newline at end of file diff --git a/extensions/rcs_tacto/pyproject.toml b/extensions/rcs_tacto/pyproject.toml index 595f08ff..21476cfd 100644 --- a/extensions/rcs_tacto/pyproject.toml +++ b/extensions/rcs_tacto/pyproject.toml @@ -12,15 +12,17 @@ dependencies = [ ] readme = "README.md" maintainers = [ + { name = "Tobias Jülg", email = "tobias.juelg@utn.de" }, { name = "Seongjin Bien", email = "seongjin.bien@utn.de" }, ] authors = [ { name = "Seongjin Bien", email = "seongjin.bien@utn.de" }, ] requires-python = ">=3.10" -classifiers = [ - "Development Status :: 3 - Alpha", - "License :: OSI Approved :: GNU Affero General Public License v3 (AGPLv3)", - "Programming Language :: Python :: 3", -] +[tool.black] +line-length = 120 +target-version = ["py311"] + +[tool.isort] +profile = "black" diff --git a/extensions/rcs_usb_cam/pyproject.toml b/extensions/rcs_usb_cam/pyproject.toml index 5309d2a3..f1ae241d 100644 --- a/extensions/rcs_usb_cam/pyproject.toml +++ b/extensions/rcs_usb_cam/pyproject.toml @@ -10,17 +10,18 @@ dependencies = [ "rcs>=0.5.0", "opencv-python~=4.10.0" ] -readme = "README.md" maintainers = [ + { name = "Tobias Jülg", email = "tobias.juelg@utn.de" }, { name = "Seongjin Bien", email = "seongjin.bien@utn.de" }, ] authors = [ { name = "Seongjin Bien", email = "seongjin.bien@utn.de" }, ] requires-python = ">=3.10" -classifiers = [ - "Development Status :: 3 - Alpha", - "License :: OSI Approved :: GNU Affero General Public License v3 (AGPLv3)", - "Programming Language :: Python :: 3", -] +[tool.black] +line-length = 120 +target-version = ["py311"] + +[tool.isort] +profile = "black" \ No newline at end of file diff --git a/extensions/rcs_xarm7/pyproject.toml b/extensions/rcs_xarm7/pyproject.toml index 57129794..1acfebe2 100644 --- a/extensions/rcs_xarm7/pyproject.toml +++ b/extensions/rcs_xarm7/pyproject.toml @@ -20,4 +20,10 @@ authors = [ { name = "Ken Nakahara", email = "knakahara@lasr.org" }, ] requires-python = ">=3.10" -license = "AGPL-3.0-or-later" + +[tool.black] +line-length = 120 +target-version = ["py311"] + +[tool.isort] +profile = "black" From 4e15bc217cce6cd0a9505cfbc3ecc6d8ab0ce6bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20J=C3=BClg?= Date: Sun, 30 Nov 2025 17:19:32 +0100 Subject: [PATCH 04/16] fix: refactored requirements_dev.txt in makefiles --- .github/workflows/py.yaml | 4 ++-- Makefile | 2 -- README.md | 2 ++ docker/Dockerfile | 2 +- extensions/rcs_robotics_library/Makefile | 2 -- extensions/rcs_so101/Makefile | 2 -- pyproject.toml | 2 +- 7 files changed, 6 insertions(+), 10 deletions(-) diff --git a/.github/workflows/py.yaml b/.github/workflows/py.yaml index c44eff32..ad091575 100644 --- a/.github/workflows/py.yaml +++ b/.github/workflows/py.yaml @@ -21,7 +21,7 @@ jobs: python-version: "3.10" cache: "pip" - name: Install linting and formatting dependencies - run: python -m pip install -r requirements_dev.txt + run: python -m pip install -r requirements.txt - name: Check formatting run: make pycheckformat @@ -43,7 +43,7 @@ jobs: python-version: "3.11" cache: "pip" - name: Install building dependencies - run: python -m pip install -r requirements_dev.txt + run: python -m pip install -r requirements.txt - name: Install wheel run: python -m pip install wheel - name: Install the package diff --git a/Makefile b/Makefile index a1d1e0d2..bbb7bf92 100644 --- a/Makefile +++ b/Makefile @@ -16,12 +16,10 @@ cpplint: # clang-tidy -p=build --warnings-as-errors='*' $(shell find extensions/rcs_fr3/src -name '*.cpp' -o -name '*.cc' -name '*.h') gcccompile: - pip install --upgrade --requirement requirements_dev.txt cmake -DCMAKE_BUILD_TYPE=${COMPILE_MODE} -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -B build -G Ninja $(if ${PYTHON_EXECUTABLE},-DPython3_EXECUTABLE=${PYTHON_EXECUTABLE}) cmake --build build --target _core clangcompile: - pip install --upgrade --requirement requirements_dev.txt cmake -DCMAKE_BUILD_TYPE=${COMPILE_MODE} -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -B build -G Ninja $(if ${PYTHON_EXECUTABLE},-DPython3_EXECUTABLE=${PYTHON_EXECUTABLE}) cmake --build build --target _core diff --git a/README.md b/README.md index 33ab7405..c6053150 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ **Robot Control Stack (RCS)** is a unified and multilayered robot control interface over a MuJoCo simulation and real world robot currently implemented for the FR3/Panda, xArm7, UR5e and SO101. +![rcs architecture diagram](docs/_static/rcs_architecture_small.svg) + ## Installation We build and test RCS on the latest Debian and on the latest Ubuntu LTS. diff --git a/docker/Dockerfile b/docker/Dockerfile index 88354dc0..b56d6468 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -75,7 +75,7 @@ RUN pip install --upgrade pip setuptools RUN pip config --site set global.no-build-isolation false # Install development dependencies -RUN pip install -r requirements_dev.txt +RUN pip install -r requirements.txt # Install the package in editable mode (CMake + pybind11 + scikit-build-core triggered) RUN pip install -e . --no-cache-dir --verbose --no-build-isolation diff --git a/extensions/rcs_robotics_library/Makefile b/extensions/rcs_robotics_library/Makefile index 9320efb7..858bd6c9 100644 --- a/extensions/rcs_robotics_library/Makefile +++ b/extensions/rcs_robotics_library/Makefile @@ -16,12 +16,10 @@ cpplint: # clang-tidy -p=build --warnings-as-errors='*' $(shell find extensions/rcs_fr3/src -name '*.cpp' -o -name '*.cc' -name '*.h') gcccompile: - pip install --upgrade --requirement requirements_dev.txt cmake -DCMAKE_BUILD_TYPE=${COMPILE_MODE} -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -B build -G Ninja cmake --build build --target _core clangcompile: - pip install --upgrade --requirement requirements_dev.txt cmake -DCMAKE_BUILD_TYPE=${COMPILE_MODE} -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -B build -G Ninja cmake --build build --target _core diff --git a/extensions/rcs_so101/Makefile b/extensions/rcs_so101/Makefile index 5793f066..7a004ac9 100644 --- a/extensions/rcs_so101/Makefile +++ b/extensions/rcs_so101/Makefile @@ -16,12 +16,10 @@ cpplint: # clang-tidy -p=build --warnings-as-errors='*' $(shell find extensions/rcs_fr3/src -name '*.cpp' -o -name '*.cc' -name '*.h') gcccompile: - pip install --upgrade --requirement requirements_dev.txt cmake -DCMAKE_BUILD_TYPE=${COMPILE_MODE} -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -B build -G Ninja cmake --build build --target _core clangcompile: - pip install --upgrade --requirement requirements_dev.txt cmake -DCMAKE_BUILD_TYPE=${COMPILE_MODE} -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -B build -G Ninja cmake --build build --target _core diff --git a/pyproject.toml b/pyproject.toml index 8163ed2f..81f4b465 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,7 +19,7 @@ dependencies = ["websockets>=11.0", "pillow~=10.3", "python-dotenv==1.0.1", "opencv-python~=4.10.0.84", - # NOTE: when changing the mujoco version, also change it in requirements_dev.txt + # NOTE: when changing the mujoco version, also change it in requirements.txt "mujoco==3.2.6", # NOTE: Same for pinocchio (pin) "pin==3.7.0", From 529825801cd854e48ceaa214c8fa10763e9a4b9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20J=C3=BClg?= Date: Sun, 30 Nov 2025 22:04:07 +0100 Subject: [PATCH 05/16] ci: dependent workflows, caching and extension linting --- .github/workflows/cpp.yaml | 36 +++++++-- .github/workflows/extensions.yaml | 117 ++++++++++++++++++++++++++++++ .github/workflows/py.yaml | 13 ++-- 3 files changed, 153 insertions(+), 13 deletions(-) create mode 100644 .github/workflows/extensions.yaml diff --git a/.github/workflows/cpp.yaml b/.github/workflows/cpp.yaml index 525d694c..3ec1ef4e 100644 --- a/.github/workflows/cpp.yaml +++ b/.github/workflows/cpp.yaml @@ -4,7 +4,9 @@ on: pull_request: paths: - "src/**" - - ".github/workflows/**" + - "include/**" + - "extensions/**" + - ".github/workflows/cpp.yaml" push: branches: - master @@ -14,25 +16,42 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + - name: Cache apt packages + uses: actions/cache@v4 + with: + path: /var/cache/apt/archives + key: ${{ runner.os }}-apt-${{ hashFiles('debian_deps.txt') }} + restore-keys: | + ${{ runner.os }}-apt- - name: Install dependencies run: sudo apt install $(cat debian_deps.txt) - - name: Check clang format - run: make cppcheckformat - name: Set up Python 3.11 id: setup-python uses: actions/setup-python@v5 with: python-version: "3.11" cache: "pip" - - name: Clang build - run: make clangcompile PYTHON_EXECUTABLE=${{ steps.setup-python.outputs.python-path }} + - name: Install Python dependencies + run: | + pip install -r requirements.txt + - name: Check clang format + run: make cppcheckformat - name: Clang Tidy run: make cpplint + - name: Clang build + run: make clangcompile PYTHON_EXECUTABLE=${{ steps.setup-python.outputs.python-path }} build_gcc: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + - name: Cache apt packages + uses: actions/cache@v4 + with: + path: /var/cache/apt/archives + key: ${{ runner.os }}-apt-${{ hashFiles('debian_deps.txt') }} + restore-keys: | + ${{ runner.os }}-apt- - name: Install dependencies run: sudo apt install $(cat debian_deps.txt) - name: Set up Python 3.11 @@ -41,5 +60,12 @@ jobs: with: python-version: "3.11" cache: "pip" + - name: Install Python dependencies + run: | + pip install -r requirements.txt - name: GCC build run: make gcccompile PYTHON_EXECUTABLE=${{ steps.setup-python.outputs.python-path }} + + build_extensions: + needs: [build_clang, build_gcc] + uses: ./.github/workflows/extensions.yaml diff --git a/.github/workflows/extensions.yaml b/.github/workflows/extensions.yaml new file mode 100644 index 00000000..98723de0 --- /dev/null +++ b/.github/workflows/extensions.yaml @@ -0,0 +1,117 @@ +name: Extensions + +on: + workflow_call: + +jobs: + build_extensions: + strategy: + matrix: + extension: + # Python extensions + - rcs_xarm7 + - rcs_realsense + - rcs_robotiq + - rcs_tacto + - rcs_usb_cam + - rcs_zed + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Cache apt packages + uses: actions/cache@v4 + with: + path: /var/cache/apt/archives + key: ${{ runner.os }}-apt-${{ hashFiles('debian_deps.txt') }} + restore-keys: | + ${{ runner.os }}-apt- + - name: Install dependencies + run: sudo apt install $(cat debian_deps.txt) + - name: Set up Python 3.11 + id: setup-python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + cache: "pip" + + - name: Install build dependencies + run: pip install -r requirements.txt + + - name: Install rcs + run: pip install -v --no-build-isolation '.[dev]' + + - name: Install extension + run: pip install -v --no-build-isolation extensions/${{ matrix.extension }} + + build_cpp_extensions_clang: + strategy: + matrix: + extension: + - rcs_fr3 + - rcs_panda + - rcs_robotics_library + - rcs_so101 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Cache apt packages + uses: actions/cache@v4 + with: + path: /var/cache/apt/archives + key: ${{ runner.os }}-apt-${{ hashFiles('debian_deps.txt') }} + restore-keys: | + ${{ runner.os }}-apt- + - name: Install dependencies + run: sudo apt install $(cat debian_deps.txt) + - name: Set up Python 3.11 + id: setup-python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + cache: "pip" + - name: Install Python dependencies + run: | + pip install -r requirements.txt + - name: Check clang format + run: make -C extensions/${{ matrix.extension }} cppcheckformat + - name: Clang Tidy + run: make -C extensions/${{ matrix.extension }} cpplint + - name: Clang build + run: make -C extensions/${{ matrix.extension }} clangcompile PYTHON_EXECUTABLE=${{ steps.setup-python.outputs.python-path }} + + build_cpp_extensions_gcc: + strategy: + matrix: + extension: + - rcs_fr3 + - rcs_panda + - rcs_robotics_library + - rcs_so101 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Cache apt packages + uses: actions/cache@v4 + with: + path: /var/cache/apt/archives + key: ${{ runner.os }}-apt-${{ hashFiles('debian_deps.txt') }} + restore-keys: | + ${{ runner.os }}-apt- + - name: Install dependencies + run: sudo apt install $(cat debian_deps.txt) + - name: Set up Python 3.11 + id: setup-python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + cache: "pip" + - name: Install Python dependencies + run: | + pip install -r requirements.txt + pip install -v --no-build-isolation '.[dev]' + pip install -v --no-build-isolation extensions/${{ matrix.extension }} + - name: GCC build + run: make -C extensions/${{ matrix.extension }} gcccompile PYTHON_EXECUTABLE=${{ steps.setup-python.outputs.python-path }} + - name: Check that stub files are up-to-date + run: make -C extensions/${{ matrix.extension }} stubgen && git diff --exit-code + diff --git a/.github/workflows/py.yaml b/.github/workflows/py.yaml index ad091575..ce2da28b 100644 --- a/.github/workflows/py.yaml +++ b/.github/workflows/py.yaml @@ -5,7 +5,7 @@ on: paths: - "python/**" - "src/pybind/**" - - ".github/workflows/**" + - ".github/workflows/py.yaml" push: branches: - master @@ -15,10 +15,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Set up Python 3.10 + - name: Set up Python 3.11 uses: actions/setup-python@v5 with: - python-version: "3.10" + python-version: "3.11" cache: "pip" - name: Install linting and formatting dependencies run: python -m pip install -r requirements.txt @@ -26,6 +26,7 @@ jobs: run: make pycheckformat pythonpackage: + needs: format runs-on: ubuntu-latest env: CC: clang @@ -47,11 +48,7 @@ jobs: - name: Install wheel run: python -m pip install wheel - name: Install the package - run: python -m pip install --no-build-isolation . - - name: Install the fr3 extension - run: python -m pip install --no-build-isolation extensions/rcs_fr3 - - name: Install the panda extension - run: python -m pip install --no-build-isolation extensions/rcs_panda + run: python -m pip install -v --no-build-isolation '.[dev]' - name: Code linting run: make pylint - name: Check that stub files are up-to-date From edcbc2a7d8fb117567e9051d64d0ba0a406da517 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20J=C3=BClg?= Date: Mon, 1 Dec 2025 07:29:24 +0100 Subject: [PATCH 06/16] ci: fix format deps --- .github/workflows/cpp.yaml | 4 ++-- .github/workflows/extensions.yaml | 2 +- .github/workflows/py.yaml | 16 ++-------------- 3 files changed, 5 insertions(+), 17 deletions(-) diff --git a/.github/workflows/cpp.yaml b/.github/workflows/cpp.yaml index 3ec1ef4e..d91afc5b 100644 --- a/.github/workflows/cpp.yaml +++ b/.github/workflows/cpp.yaml @@ -36,8 +36,8 @@ jobs: pip install -r requirements.txt - name: Check clang format run: make cppcheckformat - - name: Clang Tidy - run: make cpplint + # - name: Clang Tidy + # run: make cpplint - name: Clang build run: make clangcompile PYTHON_EXECUTABLE=${{ steps.setup-python.outputs.python-path }} diff --git a/.github/workflows/extensions.yaml b/.github/workflows/extensions.yaml index 98723de0..6118bb73 100644 --- a/.github/workflows/extensions.yaml +++ b/.github/workflows/extensions.yaml @@ -11,7 +11,7 @@ jobs: # Python extensions - rcs_xarm7 - rcs_realsense - - rcs_robotiq + # - rcs_robotiq - rcs_tacto - rcs_usb_cam - rcs_zed diff --git a/.github/workflows/py.yaml b/.github/workflows/py.yaml index ce2da28b..40a18c07 100644 --- a/.github/workflows/py.yaml +++ b/.github/workflows/py.yaml @@ -11,20 +11,6 @@ on: - master jobs: - format: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Set up Python 3.11 - uses: actions/setup-python@v5 - with: - python-version: "3.11" - cache: "pip" - - name: Install linting and formatting dependencies - run: python -m pip install -r requirements.txt - - name: Check formatting - run: make pycheckformat - pythonpackage: needs: format runs-on: ubuntu-latest @@ -49,6 +35,8 @@ jobs: run: python -m pip install wheel - name: Install the package run: python -m pip install -v --no-build-isolation '.[dev]' + - name: Check formatting + run: make pycheckformat - name: Code linting run: make pylint - name: Check that stub files are up-to-date From 7dc2a2b6c3c1d1610fff18788b8dd27d2056f2a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20J=C3=BClg?= Date: Mon, 1 Dec 2025 07:32:14 +0100 Subject: [PATCH 07/16] format: apply cpp formatting --- extensions/rcs_fr3/src/hw/Franka.cpp | 44 ++++++------- extensions/rcs_fr3/src/hw/Franka.h | 22 +++---- extensions/rcs_fr3/src/hw/FrankaHand.cpp | 20 +++--- extensions/rcs_fr3/src/hw/FrankaHand.h | 8 +-- extensions/rcs_fr3/src/hw/main.cpp | 2 +- extensions/rcs_fr3/src/pybind/rcs.cpp | 4 +- extensions/rcs_so101/src/pybind/SO101.h | 41 +++++++------ extensions/rcs_so101/src/pybind/rcs.cpp | 7 +-- src/pybind/rcs.cpp | 78 ++++++++++++------------ src/rcs/Pose.cpp | 42 ++++++------- src/sim/SimGripper.cpp | 16 ++--- src/sim/SimGripper.h | 22 +++---- src/sim/SimRobot.h | 20 +++--- src/sim/SimTilburgHand.cpp | 14 ++--- src/sim/SimTilburgHand.h | 26 ++++---- 15 files changed, 185 insertions(+), 181 deletions(-) diff --git a/extensions/rcs_fr3/src/hw/Franka.cpp b/extensions/rcs_fr3/src/hw/Franka.cpp index 9ee70f45..1b6972a0 100644 --- a/extensions/rcs_fr3/src/hw/Franka.cpp +++ b/extensions/rcs_fr3/src/hw/Franka.cpp @@ -19,9 +19,9 @@ namespace rcs { namespace hw { -Franka::Franka(const std::string &ip, +Franka::Franka(const std::string& ip, std::optional> ik, - const std::optional &cfg) + const std::optional& cfg) : robot(ip), m_ik(ik) { // set collision behavior and impedance this->set_default_robot_behavior(); @@ -35,7 +35,7 @@ Franka::Franka(const std::string &ip, Franka::~Franka() { try { this->stop_control_thread(); - } catch (const franka::Exception &e) { + } catch (const franka::Exception& e) { std::cerr << "Exception in ~Franka(): " << e.what() << std::endl; } } @@ -45,7 +45,7 @@ Franka::~Franka() { * @param cfg The configuration for the robot, it should be a FrankaConfig type * otherwise the call will fail */ -bool Franka::set_config(const FrankaConfig &cfg) { +bool Franka::set_config(const FrankaConfig& cfg) { this->cfg = cfg; this->cfg.speed_factor = std::min(std::max(cfg.speed_factor, 0.0), 1.0); @@ -66,16 +66,16 @@ bool Franka::set_config(const FrankaConfig &cfg) { return true; } -FrankaConfig *Franka::get_config() { +FrankaConfig* Franka::get_config() { // copy config to heap - FrankaConfig *cfg = new FrankaConfig(); + FrankaConfig* cfg = new FrankaConfig(); *cfg = this->cfg; return cfg; } -FrankaState *Franka::get_state() { +FrankaState* Franka::get_state() { // dummy state until we define a prober state - FrankaState *state = new FrankaState(); + FrankaState* state = new FrankaState(); return state; } @@ -105,7 +105,7 @@ common::Pose Franka::get_cartesian_position() { return x; } -void Franka::set_joint_position(const common::VectorXd &q) { +void Franka::set_joint_position(const common::VectorXd& q) { if (this->cfg.async_control) { this->controller_set_joint_position(q); return; @@ -134,7 +134,7 @@ void Franka::set_guiding_mode(bool x, bool y, bool z, bool roll, bool pitch, this->robot.setGuidingMode(activated, elbow); } -void PInverse(const Eigen::MatrixXd &M, Eigen::MatrixXd &M_inv, +void PInverse(const Eigen::MatrixXd& M, Eigen::MatrixXd& M_inv, double epsilon = 0.00025) { Eigen::JacobiSVD svd( M, Eigen::ComputeFullU | Eigen::ComputeFullV); @@ -153,7 +153,7 @@ void PInverse(const Eigen::MatrixXd &M, Eigen::MatrixXd &M_inv, M_inv = Eigen::MatrixXd(svd.matrixV() * S_inv * svd.matrixU().transpose()); } -void TorqueSafetyGuardFn(std::array &tau_d_array, double min_torque, +void TorqueSafetyGuardFn(std::array& tau_d_array, double min_torque, double max_torque) { for (size_t i = 0; i < tau_d_array.size(); i++) { if (tau_d_array[i] < min_torque) { @@ -164,7 +164,7 @@ void TorqueSafetyGuardFn(std::array &tau_d_array, double min_torque, } } -void Franka::controller_set_joint_position(const common::Vector7d &desired_q) { +void Franka::controller_set_joint_position(const common::Vector7d& desired_q) { // from deoxys/config/osc-position-controller.yml double traj_interpolation_time_fraction = 1.0; // in s // form deoxys/config/charmander.yml @@ -199,7 +199,7 @@ void Franka::controller_set_joint_position(const common::Vector7d &desired_q) { } void Franka::osc_set_cartesian_position( - const common::Pose &desired_pose_EE_in_base_frame) { + const common::Pose& desired_pose_EE_in_base_frame) { // from deoxys/config/osc-position-controller.yml double traj_interpolation_time_fraction = 1.0; // form deoxys/config/charmander.yml @@ -293,7 +293,7 @@ void Franka::osc() { joint_min_ << -2.8973, -1.7628, -2.8973, -3.0718, -2.8973, -0.0175, -2.8973; avoidance_weights_ << 1., 1., 1., 1., 1., 10., 10.; - this->robot.control([&](const franka::RobotState &robot_state, + this->robot.control([&](const franka::RobotState& robot_state, franka::Duration period) -> franka::Torques { std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now(); @@ -484,7 +484,7 @@ void Franka::joint_controller() { joint_max_ << 2.8978, 1.7628, 2.8973, -0.0698, 2.8973, 3.7525, 2.8973; joint_min_ << -2.8973, -1.7628, -2.8973, -3.0718, -2.8973, -0.0175, -2.8973; - this->robot.control([&](const franka::RobotState &robot_state, + this->robot.control([&](const franka::RobotState& robot_state, franka::Duration period) -> franka::Torques { std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now(); @@ -570,7 +570,7 @@ void Franka::zero_torque_controller() { {{100.0, 100.0, 100.0, 100.0, 100.0, 100.0}}); this->controller_time = 0.0; - this->robot.control([&](const franka::RobotState &robot_state, + this->robot.control([&](const franka::RobotState& robot_state, franka::Duration period) -> franka::Torques { this->interpolator_mutex.lock(); this->curr_state = robot_state; @@ -613,7 +613,7 @@ void Franka::double_tap_robot_to_continue() { auto last_time_something_happened = std::chrono::system_clock::now(); auto last_time_something_touched = std::chrono::system_clock::now(); start_force << s.O_F_ext_hat_K[0], s.O_F_ext_hat_K[1], s.O_F_ext_hat_K[2]; - this->robot.read([&](const franka::RobotState &robot_state) { + this->robot.read([&](const franka::RobotState& robot_state) { Eigen::Vector3d force; force << robot_state.O_F_ext_hat_K[0], robot_state.O_F_ext_hat_K[1], robot_state.O_F_ext_hat_K[2]; @@ -663,7 +663,7 @@ std::optional> Franka::get_ik() { return this->m_ik; } -void Franka::set_cartesian_position(const common::Pose &x) { +void Franka::set_cartesian_position(const common::Pose& x) { // pose is assumed to be in the robots coordinate frame if (this->cfg.async_control) { this->osc_set_cartesian_position(x); @@ -691,7 +691,7 @@ void Franka::set_cartesian_position(const common::Pose &x) { } } -void Franka::set_cartesian_position_ik(const common::Pose &pose) { +void Franka::set_cartesian_position_ik(const common::Pose& pose) { if (!this->m_ik.has_value()) { throw std::runtime_error( "No inverse kinematics was provided. Cannot use IK to set cartesian " @@ -714,14 +714,14 @@ common::Pose Franka::get_base_pose_in_world_coordinates() { : common::Pose(); } -void Franka::set_cartesian_position_internal(const common::Pose &pose, +void Franka::set_cartesian_position_internal(const common::Pose& pose, double max_time, std::optional elbow, std::optional max_force) { // TODO: use speed factor instead of max_time common::Pose initial_pose = this->get_cartesian_position(); - auto force_stop_condition = [&max_force](const franka::RobotState &state, + auto force_stop_condition = [&max_force](const franka::RobotState& state, const double progress) { Eigen::Vector3d force; force << state.O_F_ext_hat_K[0], state.O_F_ext_hat_K[1], @@ -737,7 +737,7 @@ void Franka::set_cartesian_position_internal(const common::Pose &pose, this->robot.control( [&force_stop_condition, &initial_elbow, &elbow, &max_force, &time, &max_time, &initial_pose, &should_stop, - &pose](const franka::RobotState &state, + &pose](const franka::RobotState& state, franka::Duration time_step) -> franka::CartesianPose { time += time_step.toSec(); if (time == 0) { diff --git a/extensions/rcs_fr3/src/hw/Franka.h b/extensions/rcs_fr3/src/hw/Franka.h index d25574f3..fe4a5af4 100644 --- a/extensions/rcs_fr3/src/hw/Franka.h +++ b/extensions/rcs_fr3/src/hw/Franka.h @@ -68,31 +68,31 @@ class Franka : public common::Robot { void zero_torque_controller(); public: - Franka(const std::string &ip, + Franka(const std::string& ip, std::optional> ik = std::nullopt, - const std::optional &cfg = std::nullopt); + const std::optional& cfg = std::nullopt); ~Franka() override; - bool set_config(const FrankaConfig &cfg); + bool set_config(const FrankaConfig& cfg); - FrankaConfig *get_config() override; + FrankaConfig* get_config() override; - FrankaState *get_state() override; + FrankaState* get_state() override; void set_default_robot_behavior(); common::Pose get_cartesian_position() override; - void set_joint_position(const common::VectorXd &q) override; + void set_joint_position(const common::VectorXd& q) override; common::VectorXd get_joint_position() override; void set_guiding_mode(bool x, bool y, bool z, bool roll, bool pitch, bool yaw, bool elbow); - void controller_set_joint_position(const common::Vector7d &desired_q); + void controller_set_joint_position(const common::Vector7d& desired_q); void osc_set_cartesian_position( - const common::Pose &desired_pose_EE_in_base_frame); + const common::Pose& desired_pose_EE_in_base_frame); void zero_torque_guiding(); void stop_control_thread(); @@ -105,16 +105,16 @@ class Franka : public common::Robot { void double_tap_robot_to_continue(); - void set_cartesian_position(const common::Pose &pose) override; + void set_cartesian_position(const common::Pose& pose) override; std::optional> get_ik() override; - void set_cartesian_position_internal(const common::Pose &pose, + void set_cartesian_position_internal(const common::Pose& pose, double max_time, std::optional elbow, std::optional max_force = 5); - void set_cartesian_position_ik(const common::Pose &x); + void set_cartesian_position_ik(const common::Pose& x); common::Pose get_base_pose_in_world_coordinates() override; diff --git a/extensions/rcs_fr3/src/hw/FrankaHand.cpp b/extensions/rcs_fr3/src/hw/FrankaHand.cpp index 8adea316..8e6b9005 100644 --- a/extensions/rcs_fr3/src/hw/FrankaHand.cpp +++ b/extensions/rcs_fr3/src/hw/FrankaHand.cpp @@ -12,7 +12,7 @@ namespace rcs { namespace hw { -FrankaHand::FrankaHand(const std::string &ip, const FHConfig &cfg) +FrankaHand::FrankaHand(const std::string& ip, const FHConfig& cfg) : gripper(ip), cfg{} { this->cfg = cfg; this->m_reset(); @@ -21,12 +21,12 @@ FrankaHand::FrankaHand(const std::string &ip, const FHConfig &cfg) FrankaHand::~FrankaHand() { try { this->m_stop(); - } catch (const franka::Exception &e) { + } catch (const franka::Exception& e) { std::cerr << "Exception in ~FrankaHand(): " << e.what() << std::endl; } } -bool FrankaHand::set_config(const FHConfig &cfg) { +bool FrankaHand::set_config(const FHConfig& cfg) { franka::GripperState gripper_state = this->gripper.readOnce(); if (gripper_state.max_width < cfg.grasping_width) { return false; @@ -35,19 +35,19 @@ bool FrankaHand::set_config(const FHConfig &cfg) { return true; } -FHConfig *FrankaHand::get_config() { +FHConfig* FrankaHand::get_config() { // copy config to heap - FHConfig *cfg = new FHConfig(); + FHConfig* cfg = new FHConfig(); *cfg = this->cfg; return cfg; } -FHState *FrankaHand::get_state() { +FHState* FrankaHand::get_state() { franka::GripperState gripper_state = this->gripper.readOnce(); if (std::abs(gripper_state.max_width - this->cfg.grasping_width) > 0.01) { this->max_width = gripper_state.max_width - 0.001; } - FHState *state = new FHState(); + FHState* state = new FHState(); state->width = gripper_state.width / gripper_state.max_width; state->is_grasped = gripper_state.is_grasped; state->temperature = gripper_state.temperature; @@ -81,7 +81,7 @@ double FrankaHand::get_normalized_width() { void FrankaHand::m_stop() { try { this->gripper.stop(); - } catch (const franka::Exception &e) { + } catch (const franka::Exception& e) { std::cerr << "FrankaHand::m_stop: " << e.what() << std::endl; } this->m_wait(); @@ -137,7 +137,7 @@ void FrankaHand::grasp() { this->is_moving = true; try { this->gripper.grasp(0, this->cfg.speed, this->cfg.force, 1, 1); - } catch (const franka::CommandException &e) { + } catch (const franka::CommandException& e) { std::cerr << "franka hand command exception ignored grasp" << std::endl; } this->is_moving = false; @@ -163,7 +163,7 @@ void FrankaHand::open() { this->gripper.move(this->max_width, this->cfg.speed); // this->gripper.grasp(this->max_width, this->cfg.speed, this->cfg.force, // 1, 1); - } catch (const franka::CommandException &e) { + } catch (const franka::CommandException& e) { std::cerr << "franka hand command exception ignored open" << std::endl; } this->is_moving = false; diff --git a/extensions/rcs_fr3/src/hw/FrankaHand.h b/extensions/rcs_fr3/src/hw/FrankaHand.h index 390cbc0c..58a723da 100644 --- a/extensions/rcs_fr3/src/hw/FrankaHand.h +++ b/extensions/rcs_fr3/src/hw/FrankaHand.h @@ -54,14 +54,14 @@ class FrankaHand : public common::Gripper { void m_wait(); public: - FrankaHand(const std::string &ip, const FHConfig &cfg); + FrankaHand(const std::string& ip, const FHConfig& cfg); ~FrankaHand() override; - bool set_config(const FHConfig &cfg); + bool set_config(const FHConfig& cfg); - FHConfig *get_config() override; + FHConfig* get_config() override; - FHState *get_state() override; + FHState* get_state() override; void reset() override; diff --git a/extensions/rcs_fr3/src/hw/main.cpp b/extensions/rcs_fr3/src/hw/main.cpp index e76e66b4..6e0a4922 100644 --- a/extensions/rcs_fr3/src/hw/main.cpp +++ b/extensions/rcs_fr3/src/hw/main.cpp @@ -33,7 +33,7 @@ int main() { robot.set_cartesian_position_internal(rs, 5.0, std::nullopt); // robot.automatic_error_recovery(); - } catch (const franka::Exception &e) { + } catch (const franka::Exception& e) { cout << e.what() << endl; return -1; } diff --git a/extensions/rcs_fr3/src/pybind/rcs.cpp b/extensions/rcs_fr3/src/pybind/rcs.cpp index 67e59c00..ea56afff 100644 --- a/extensions/rcs_fr3/src/pybind/rcs.cpp +++ b/extensions/rcs_fr3/src/pybind/rcs.cpp @@ -104,7 +104,7 @@ PYBIND11_MODULE(_core, m) { (py::object)py::module_::import("rcs").attr("common").attr("Robot"); py::class_>(hw, "Franka", robot) - .def(py::init>>(), py::arg("ip"), py::arg("ik") = std::nullopt) .def("set_config", &rcs::hw::Franka::set_config, py::arg("cfg")) @@ -138,7 +138,7 @@ PYBIND11_MODULE(_core, m) { (py::object)py::module_::import("rcs").attr("common").attr("Gripper"); py::class_>( hw, "FrankaHand", gripper) - .def(py::init(), + .def(py::init(), py::arg("ip"), py::arg("cfg")) .def("get_config", &rcs::hw::FrankaHand::get_config) .def("get_state", &rcs::hw::FrankaHand::get_state) diff --git a/extensions/rcs_so101/src/pybind/SO101.h b/extensions/rcs_so101/src/pybind/SO101.h index ed25318f..bdf058ea 100644 --- a/extensions/rcs_so101/src/pybind/SO101.h +++ b/extensions/rcs_so101/src/pybind/SO101.h @@ -9,20 +9,19 @@ #include #include #include -#include - #include #include #include #include #include #include +#include namespace rcs { namespace so101 { class SO101IK : public rcs::common::Kinematics { -private: + private: const double eps = 1e-4; const int IT_MAX = 1000; const double DT = 1e-1; @@ -35,7 +34,8 @@ class SO101IK : public rcs::common::Kinematics { pinocchio::Data data; public: - SO101IK(const std::string& path, const std::string& frame_id, bool urdf = true) + SO101IK(const std::string& path, const std::string& frame_id, + bool urdf = true) : model() { if (urdf) { pinocchio::urdf::buildModel(path, this->model); @@ -53,10 +53,12 @@ class SO101IK : public rcs::common::Kinematics { const rcs::common::Pose& pose, const rcs::common::VectorXd& q0, const rcs::common::Pose& tcp_offset = rcs::common::Pose::Identity()) override { - // --- Tunables (could be class members) ------------------------------------ - const double WP = 1.0; // position weight - const double WO = 0.12; // orientation (pitch+yaw) weight - const double WO_ROLL = 0.03; // orientation roll weight (let it "float" more) + // --- Tunables (could be class members) + // ------------------------------------ + const double WP = 1.0; // position weight + const double WO = 0.12; // orientation (pitch+yaw) weight + const double WO_ROLL = + 0.03; // orientation roll weight (let it "float" more) const double ORI_TOL = 5.0 * M_PI / 180.0; // 5 deg tolerance (dead-zone) const double ORI_CAP = 0.6; // cap on |eo| scaling (rad/s-equivalent per iter) @@ -78,7 +80,7 @@ class SO101IK : public rcs::common::Kinematics { bool success = false; // Pre-allocations - rcs::common::Vector6d err, err_w; // 6x1 + rcs::common::Vector6d err, err_w; // 6x1 Eigen::Vector3d ep, eo; // position/orientation parts Eigen::VectorXd v(model.nv); // nv x 1 pinocchio::Data::Matrix6 JJt; // 6x6 @@ -106,8 +108,9 @@ class SO101IK : public rcs::common::Kinematics { ep = err.head<3>(); eo = err.tail<3>(); - // ---- Orientation tolerance (dead-zone + soft cap) ---------------------- - // If |eo| is small, ignore it completely (prevents twitch). + // ---- Orientation tolerance (dead-zone + soft cap) + // ---------------------- If |eo| is small, ignore it completely (prevents + // twitch). const double eo_norm = eo.norm(); if (eo_norm < ORI_TOL) { eo.setZero(); @@ -140,9 +143,10 @@ class SO101IK : public rcs::common::Kinematics { pinocchio::Jlog6(iMd.inverse(), Jlog); J = -Jlog * J; // tangent-space Jacobian for the error you’re minimizing - // ---- Weighted damped least-squares ------------------------------------- - // Apply sqrt-weights on rows: this prioritizes translation > orientation, - // and de-weights tool roll further. + // ---- Weighted damped least-squares + // ------------------------------------- Apply sqrt-weights on rows: this + // prioritizes translation > orientation, and de-weights tool roll + // further. const auto Jw = Wsqrt * J; // 6xnv err_w = Wsqrt * err; // 6x1 @@ -168,10 +172,11 @@ class SO101IK : public rcs::common::Kinematics { v.noalias() = -Jw.transpose() * JJt.ldlt().solve(err_w); // ------------------------------------------------------------------------ - // ---- Step-size limiter in task space to avoid sudden jumps ------------- - // Predict task step and scale if too large + // ---- Step-size limiter in task space to avoid sudden jumps + // ------------- Predict task step and scale if too large Eigen::Matrix task_step = J * v * this->DT; - double step_norm = task_step.head<3>().norm() + task_step.tail<3>().norm(); + double step_norm = + task_step.head<3>().norm() + task_step.tail<3>().norm(); if (step_norm > STEP_CAP && step_norm > 1e-9) { const double scale = STEP_CAP / step_norm; v *= scale; @@ -199,7 +204,7 @@ class SO101IK : public rcs::common::Kinematics { q.head(q0.size()) = q0; pinocchio::framesForwardKinematics(model, data, q); rcs::common::Pose pose(data.oMf[this->FRAME_ID].rotation(), - data.oMf[this->FRAME_ID].translation()); + data.oMf[this->FRAME_ID].translation()); // apply the tcp offset return pose * tcp_offset.inverse(); diff --git a/extensions/rcs_so101/src/pybind/rcs.cpp b/extensions/rcs_so101/src/pybind/rcs.cpp index bc359f70..f5f1ff55 100644 --- a/extensions/rcs_so101/src/pybind/rcs.cpp +++ b/extensions/rcs_so101/src/pybind/rcs.cpp @@ -38,9 +38,8 @@ PYBIND11_MODULE(_core, m) { py::object kinematics = (py::object)py::module_::import("rcs").attr("common").attr("Kinematics"); - py::class_>( + py::class_>( ik, "SO101IK", kinematics) - .def(py::init(), py::arg("path"), - py::arg("frame_id"), py::arg("urdf") = true); + .def(py::init(), + py::arg("path"), py::arg("frame_id"), py::arg("urdf") = true); } diff --git a/src/pybind/rcs.cpp b/src/pybind/rcs.cpp index 0bb99825..4c2f5c78 100644 --- a/src/pybind/rcs.cpp +++ b/src/pybind/rcs.cpp @@ -33,13 +33,13 @@ class PyRobot : public rcs::common::Robot { public: using rcs::common::Robot::Robot; // Inherit constructors - rcs::common::RobotConfig *get_config() override { - PYBIND11_OVERRIDE_PURE(rcs::common::RobotConfig *, rcs::common::Robot, + rcs::common::RobotConfig* get_config() override { + PYBIND11_OVERRIDE_PURE(rcs::common::RobotConfig*, rcs::common::Robot, get_config, ); } - rcs::common::RobotState *get_state() override { - PYBIND11_OVERRIDE_PURE(rcs::common::RobotState *, rcs::common::Robot, + rcs::common::RobotState* get_state() override { + PYBIND11_OVERRIDE_PURE(rcs::common::RobotState*, rcs::common::Robot, get_state, ); } @@ -48,7 +48,7 @@ class PyRobot : public rcs::common::Robot { get_cartesian_position, ); } - void set_joint_position(const rcs::common::VectorXd &q) override { + void set_joint_position(const rcs::common::VectorXd& q) override { PYBIND11_OVERRIDE_PURE(void, rcs::common::Robot, set_joint_position, q); } @@ -78,7 +78,7 @@ class PyRobot : public rcs::common::Robot { get_base_pose_in_world_coordinates, ); } - void set_cartesian_position(const rcs::common::Pose &pose) override { + void set_cartesian_position(const rcs::common::Pose& pose) override { PYBIND11_OVERRIDE_PURE(void, rcs::common::Robot, set_cartesian_position, pose); } @@ -91,13 +91,13 @@ class PyGripper : public rcs::common::Gripper { public: using rcs::common::Gripper::Gripper; // Inherit constructors - rcs::common::GripperConfig *get_config() override { - PYBIND11_OVERRIDE_PURE(rcs::common::GripperConfig *, rcs::common::Gripper, + rcs::common::GripperConfig* get_config() override { + PYBIND11_OVERRIDE_PURE(rcs::common::GripperConfig*, rcs::common::Gripper, get_config, ); } - rcs::common::GripperState *get_state() override { - PYBIND11_OVERRIDE_PURE(rcs::common::GripperState *, rcs::common::Gripper, + rcs::common::GripperState* get_state() override { + PYBIND11_OVERRIDE_PURE(rcs::common::GripperState*, rcs::common::Gripper, get_state, ); } @@ -140,17 +140,17 @@ class PyHand : public rcs::common::Hand { public: using rcs::common::Hand::Hand; // Inherit constructors - rcs::common::HandConfig *get_config() override { - PYBIND11_OVERRIDE_PURE(rcs::common::HandConfig *, rcs::common::Hand, + rcs::common::HandConfig* get_config() override { + PYBIND11_OVERRIDE_PURE(rcs::common::HandConfig*, rcs::common::Hand, get_config, ); } - rcs::common::HandState *get_state() override { - PYBIND11_OVERRIDE_PURE(rcs::common::HandState *, rcs::common::Hand, + rcs::common::HandState* get_state() override { + PYBIND11_OVERRIDE_PURE(rcs::common::HandState*, rcs::common::Hand, get_state, ); } - void set_normalized_joint_poses(const rcs::common::VectorXd &q) override { + void set_normalized_joint_poses(const rcs::common::VectorXd& q) override { PYBIND11_OVERRIDE_PURE(void, rcs::common::Hand, set_normalized_joint_poses, q); } @@ -211,9 +211,9 @@ PYBIND11_MODULE(_core, m) { common.def("FrankaHandTCPOffset", &rcs::common::FrankaHandTCPOffset); py::class_(common, "BaseCameraConfig") - .def(py::init(), - py::arg("identifier"), py::arg("frame_rate"), - py::arg("resolution_width"), py::arg("resolution_height")) + .def(py::init(), py::arg("identifier"), + py::arg("frame_rate"), py::arg("resolution_width"), + py::arg("resolution_height")) .def_readwrite("identifier", &rcs::common::BaseCameraConfig::identifier) .def_readwrite("frame_rate", &rcs::common::BaseCameraConfig::frame_rate) .def_readwrite("resolution_width", @@ -236,7 +236,7 @@ PYBIND11_MODULE(_core, m) { .def("__str__", &rcs::common::RPY::str) .def(py::self + py::self) .def(py::pickle( - [](const rcs::common::RPY &p) { // dump + [](const rcs::common::RPY& p) { // dump return py::make_tuple(p.roll, p.pitch, p.yaw); }, [](py::tuple t) { // load @@ -246,20 +246,20 @@ PYBIND11_MODULE(_core, m) { py::class_(common, "Pose") .def(py::init<>()) - .def(py::init(), py::arg("pose_matrix")) - .def(py::init(), + .def(py::init(), py::arg("pose_matrix")) + .def(py::init(), py::arg("rotation"), py::arg("translation")) - .def(py::init(), + .def(py::init(), py::arg("quaternion"), py::arg("translation")) - .def(py::init(), + .def(py::init(), py::arg("rpy"), py::arg("translation")) - .def(py::init(), + .def(py::init(), py::arg("rpy_vector"), py::arg("translation")) - .def(py::init(), py::arg("translation")) - .def(py::init(), py::arg("quaternion")) - .def(py::init(), py::arg("rpy")) - .def(py::init(), py::arg("rotation")) - .def(py::init(), py::arg("pose")) + .def(py::init(), py::arg("translation")) + .def(py::init(), py::arg("quaternion")) + .def(py::init(), py::arg("rpy")) + .def(py::init(), py::arg("rotation")) + .def(py::init(), py::arg("pose")) .def("translation", &rcs::common::Pose::translation) .def("rotation_m", &rcs::common::Pose::rotation_m) .def("rotation_q", &rcs::common::Pose::rotation_q) @@ -279,7 +279,7 @@ PYBIND11_MODULE(_core, m) { .def("__str__", &rcs::common::Pose::str) .def(py::self * py::self) .def(py::pickle( - [](const rcs::common::Pose &p) { // dump + [](const rcs::common::Pose& p) { // dump return p.affine_array(); }, [](std::array t) { // load @@ -295,7 +295,7 @@ PYBIND11_MODULE(_core, m) { py::class_>(common, "Pin") - .def(py::init(), + .def(py::init(), py::arg("path"), py::arg("frame_id") = "fr3_link8", py::arg("urdf") = true); @@ -493,7 +493,7 @@ PYBIND11_MODULE(_core, m) { py::class_>(sim, "Sim") .def(py::init([](long m, long d) { - return std::make_shared((mjModel *)m, (mjData *)d); + return std::make_shared((mjModel*)m, (mjData*)d); }), py::arg("mjmdl"), py::arg("mjdata")) .def("step_until_convergence", &rcs::sim::Sim::step_until_convergence, @@ -509,7 +509,7 @@ PYBIND11_MODULE(_core, m) { py::class_>(sim, "SimGripper") .def(py::init, - const rcs::sim::SimGripperConfig &>(), + const rcs::sim::SimGripperConfig&>(), py::arg("sim"), py::arg("cfg")) .def("get_config", &rcs::sim::SimGripper::get_config) .def("get_state", &rcs::sim::SimGripper::get_state) @@ -562,7 +562,7 @@ PYBIND11_MODULE(_core, m) { py::class_>(sim, "SimTilburgHand") .def(py::init, - const rcs::sim::SimTilburgHandConfig &>(), + const rcs::sim::SimTilburgHandConfig&>(), py::arg("sim"), py::arg("cfg")) .def("get_config", &rcs::sim::SimTilburgHand::get_config) .def("get_state", &rcs::sim::SimTilburgHand::get_state) @@ -576,7 +576,7 @@ PYBIND11_MODULE(_core, m) { .export_values(); py::class_( sim, "SimCameraConfig") - .def(py::init(), + .def(py::init(), py::arg("identifier"), py::arg("frame_rate"), py::arg("resolution_width"), py::arg("resolution_height"), py::arg("type") = rcs::sim::CameraType::fixed) @@ -599,15 +599,15 @@ PYBIND11_MODULE(_core, m) { .def("get_timestamp_frameset", &rcs::sim::SimCameraSet::get_timestamp_frameset, py::arg("ts")); py::class_(sim, "GuiClient") - .def(py::init(), py::arg("id")) + .def(py::init(), py::arg("id")) .def("get_model_bytes", - [](const rcs::sim::GuiClient &self) { + [](const rcs::sim::GuiClient& self) { auto s = self.get_model_bytes(); return py::bytes(s); }) .def("set_model_and_data", - [](rcs::sim::GuiClient &self, long m, long d) { - self.set_model_and_data((mjModel *)m, (mjData *)d); + [](rcs::sim::GuiClient& self, long m, long d) { + self.set_model_and_data((mjModel*)m, (mjData*)d); }) .def("sync", &rcs::sim::GuiClient::sync); } diff --git a/src/rcs/Pose.cpp b/src/rcs/Pose.cpp index 4a5176aa..76ed371a 100644 --- a/src/rcs/Pose.cpp +++ b/src/rcs/Pose.cpp @@ -21,85 +21,85 @@ Pose::Pose() { this->m_rotation = IdentityRotQuat(); } -Pose::Pose(const Eigen::Affine3d &pose_matrix) { +Pose::Pose(const Eigen::Affine3d& pose_matrix) { this->m_translation = pose_matrix.translation(); this->m_rotation = Eigen::Quaterniond(pose_matrix.rotation()); this->m_rotation.normalize(); } -Pose::Pose(const std::array &pose) +Pose::Pose(const std::array& pose) : Pose(array2eigen<4, 4>(pose)) {} -Pose::Pose(const Eigen::Matrix4d &pose) { +Pose::Pose(const Eigen::Matrix4d& pose) { Eigen::Affine3d affine_pose = Eigen::Affine3d(pose); this->m_translation = affine_pose.translation(); this->m_rotation = Eigen::Quaterniond(affine_pose.rotation()); this->m_rotation.normalize(); } -Pose::Pose(const Eigen::Matrix3d &rotation, - const Eigen::Vector3d &translation) { +Pose::Pose(const Eigen::Matrix3d& rotation, + const Eigen::Vector3d& translation) { this->m_translation = translation; this->m_rotation = Eigen::Quaterniond(rotation); this->m_rotation.normalize(); } -Pose::Pose(const Eigen::Vector4d &quaternion, - const Eigen::Vector3d &translation) { +Pose::Pose(const Eigen::Vector4d& quaternion, + const Eigen::Vector3d& translation) { this->m_translation = translation; this->m_rotation = Eigen::Quaterniond(quaternion); this->m_rotation.normalize(); } -Pose::Pose(const Eigen::Quaterniond &rotation, - const Eigen::Vector3d &translation) { +Pose::Pose(const Eigen::Quaterniond& rotation, + const Eigen::Vector3d& translation) { this->m_translation = translation; this->m_rotation = rotation; this->m_rotation.normalize(); } -Pose::Pose(const RPY &rotation, const Eigen::Vector3d &translation) { +Pose::Pose(const RPY& rotation, const Eigen::Vector3d& translation) { this->m_translation = translation; this->m_rotation = rotation.as_quaternion(); this->m_rotation.normalize(); } -Pose::Pose(const Eigen::Vector3d &rotation, - const Eigen::Vector3d &translation) { +Pose::Pose(const Eigen::Vector3d& rotation, + const Eigen::Vector3d& translation) { this->m_translation = translation; this->m_rotation = RPY(rotation).as_quaternion(); this->m_rotation.normalize(); } -Pose::Pose(const Eigen::Vector3d &translation) { +Pose::Pose(const Eigen::Vector3d& translation) { this->m_translation = translation; this->m_rotation = IdentityRotQuat(); } -Pose::Pose(const Eigen::Quaterniond &quaternion) { +Pose::Pose(const Eigen::Quaterniond& quaternion) { this->m_translation = IdentityTranslation(); this->m_rotation = quaternion; this->m_rotation.normalize(); } -Pose::Pose(const Eigen::Vector4d &quaternion) { +Pose::Pose(const Eigen::Vector4d& quaternion) { this->m_translation = IdentityTranslation(); this->m_rotation = Eigen::Quaterniond(quaternion); this->m_rotation.normalize(); } -Pose::Pose(const RPY &rpy) { +Pose::Pose(const RPY& rpy) { this->m_translation = IdentityTranslation(); this->m_rotation = rpy.as_quaternion(); this->m_rotation.normalize(); } -Pose::Pose(const Eigen::Matrix3d &rotation) { +Pose::Pose(const Eigen::Matrix3d& rotation) { this->m_translation = IdentityTranslation(); this->m_rotation = Eigen::Quaterniond(rotation); } -Pose::Pose(const Pose &pose) { +Pose::Pose(const Pose& pose) { this->m_translation = pose.translation(); this->m_rotation = pose.quaternion(); } @@ -137,7 +137,7 @@ RPY Pose::rotation_rpy() const { return RPY{rpy_vec.z(), rpy_vec.y(), rpy_vec.x()}; } -Pose Pose::interpolate(const Pose &dest_pose, double progress) const { +Pose Pose::interpolate(const Pose& dest_pose, double progress) const { if (progress > 1) { progress = 1; } @@ -170,7 +170,7 @@ std::string Pose::str() const { return ss.str(); } -Pose Pose::operator*(const Pose &pose_b) const { +Pose Pose::operator*(const Pose& pose_b) const { Eigen::Vector3d trans = this->m_rotation * pose_b.translation() + this->m_translation; Eigen::Quaterniond rot = this->m_rotation * pose_b.m_rotation; @@ -205,7 +205,7 @@ Pose Pose::inverse() const { return Pose(new_rot, -(new_rot * this->m_translation)); } -bool Pose::is_close(const Pose &other, double eps_r, double eps_t) const { +bool Pose::is_close(const Pose& other, double eps_r, double eps_t) const { return (this->translation() - other.translation()).lpNorm<1>() < eps_t && this->quaternion().angularDistance(other.quaternion()) < eps_r; } diff --git a/src/sim/SimGripper.cpp b/src/sim/SimGripper.cpp index 5542d6ac..7bf6ec0e 100644 --- a/src/sim/SimGripper.cpp +++ b/src/sim/SimGripper.cpp @@ -10,7 +10,7 @@ namespace rcs { namespace sim { -SimGripper::SimGripper(std::shared_ptr sim, const SimGripperConfig &cfg) +SimGripper::SimGripper(std::shared_ptr sim, const SimGripperConfig& cfg) : sim{sim}, cfg{cfg}, joint_ids{} { this->state = SimGripperState(); this->actuator_id = @@ -42,8 +42,8 @@ SimGripper::SimGripper(std::shared_ptr sim, const SimGripperConfig &cfg) SimGripper::~SimGripper() {} -void SimGripper::add_collision_geoms(const std::vector &cgeoms_str, - std::set &cgeoms_set, +void SimGripper::add_collision_geoms(const std::vector& cgeoms_str, + std::set& cgeoms_set, bool clear_before) { if (clear_before) { cgeoms_set.clear(); @@ -59,22 +59,22 @@ void SimGripper::add_collision_geoms(const std::vector &cgeoms_str, } } -bool SimGripper::set_config(const SimGripperConfig &cfg) { +bool SimGripper::set_config(const SimGripperConfig& cfg) { this->cfg = cfg; this->add_collision_geoms(cfg.ignored_collision_geoms, this->ignored_collision_geoms, true); return true; } -SimGripperConfig *SimGripper::get_config() { +SimGripperConfig* SimGripper::get_config() { // copy config to heap - SimGripperConfig *cfg = new SimGripperConfig(); + SimGripperConfig* cfg = new SimGripperConfig(); *cfg = this->cfg; return cfg; } -SimGripperState *SimGripper::get_state() { - SimGripperState *state = new SimGripperState(); +SimGripperState* SimGripper::get_state() { + SimGripperState* state = new SimGripperState(); *state = this->state; return state; } diff --git a/src/sim/SimGripper.h b/src/sim/SimGripper.h index 6e526704..9d19df79 100644 --- a/src/sim/SimGripper.h +++ b/src/sim/SimGripper.h @@ -29,17 +29,17 @@ struct SimGripperConfig : common::GripperConfig { std::vector joints = {"finger_joint1", "finger_joint2"}; std::string actuator = "actuator8"; - void add_id(const std::string &id) { - for (auto &s : this->collision_geoms) { + void add_id(const std::string& id) { + for (auto& s : this->collision_geoms) { s = s + "_" + id; } - for (auto &s : this->collision_geoms_fingers) { + for (auto& s : this->collision_geoms_fingers) { s = s + "_" + id; } - for (auto &s : this->ignored_collision_geoms) { + for (auto& s : this->ignored_collision_geoms) { s = s + "_" + id; } - for (auto &s : this->joints) { + for (auto& s : this->joints) { s = s + "_" + id; } this->actuator = this->actuator + "_" + id; @@ -65,19 +65,19 @@ class SimGripper : public common::Gripper { std::set cgeom; std::set cfgeom; std::set ignored_collision_geoms; - void add_collision_geoms(const std::vector &cgeoms_str, - std::set &cgeoms_set, bool clear_before); + void add_collision_geoms(const std::vector& cgeoms_str, + std::set& cgeoms_set, bool clear_before); void m_reset(); public: - SimGripper(std::shared_ptr sim, const SimGripperConfig &cfg); + SimGripper(std::shared_ptr sim, const SimGripperConfig& cfg); ~SimGripper() override; - bool set_config(const SimGripperConfig &cfg); + bool set_config(const SimGripperConfig& cfg); - SimGripperConfig *get_config() override; + SimGripperConfig* get_config() override; - SimGripperState *get_state() override; + SimGripperState* get_state() override; // normalized width of the gripper, 0 is closed, 1 is open void set_normalized_width(double width, double force = 0) override; diff --git a/src/sim/SimRobot.h b/src/sim/SimRobot.h index ea6c73a8..206fef87 100644 --- a/src/sim/SimRobot.h +++ b/src/sim/SimRobot.h @@ -31,14 +31,14 @@ struct SimRobotConfig : common::RobotConfig { std::string base = "base"; std::string mjcf_scene_path = "assets/scenes/fr3_empty_world/scene.xml"; - void add_id(const std::string &id) { - for (auto &s : this->arm_collision_geoms) { + void add_id(const std::string& id) { + for (auto& s : this->arm_collision_geoms) { s = s + "_" + id; } - for (auto &s : this->joints) { + for (auto& s : this->joints) { s = s + "_" + id; } - for (auto &s : this->actuators) { + for (auto& s : this->actuators) { s = s + "_" + id; } this->attachment_site = this->attachment_site + "_" + id; @@ -62,18 +62,18 @@ class SimRobot : public common::Robot { std::shared_ptr ik, SimRobotConfig cfg, bool register_convergence_callback = true); ~SimRobot() override; - bool set_config(const SimRobotConfig &cfg); - SimRobotConfig *get_config() override; - SimRobotState *get_state() override; + bool set_config(const SimRobotConfig& cfg); + SimRobotConfig* get_config() override; + SimRobotState* get_state() override; common::Pose get_cartesian_position() override; - void set_joint_position(const common::VectorXd &q) override; + void set_joint_position(const common::VectorXd& q) override; common::VectorXd get_joint_position() override; void move_home() override; - void set_cartesian_position(const common::Pose &pose) override; + void set_cartesian_position(const common::Pose& pose) override; common::Pose get_base_pose_in_world_coordinates() override; std::optional> get_ik() override; void reset() override; - void set_joints_hard(const common::VectorXd &q); + void set_joints_hard(const common::VectorXd& q); void clear_collision_flag(); void close() override {}; diff --git a/src/sim/SimTilburgHand.cpp b/src/sim/SimTilburgHand.cpp index ef407545..2f817f0d 100644 --- a/src/sim/SimTilburgHand.cpp +++ b/src/sim/SimTilburgHand.cpp @@ -11,7 +11,7 @@ namespace rcs { namespace sim { SimTilburgHand::SimTilburgHand(std::shared_ptr sim, - const SimTilburgHandConfig &cfg) + const SimTilburgHandConfig& cfg) : sim{sim}, cfg{cfg} { this->state = SimTilburgHandState(); @@ -66,7 +66,7 @@ SimTilburgHand::~SimTilburgHand() {} // } // } -bool SimTilburgHand::set_config(const SimTilburgHandConfig &cfg) { +bool SimTilburgHand::set_config(const SimTilburgHandConfig& cfg) { auto current_grasp_type = this->cfg.grasp_type; this->cfg = cfg; if (!this->set_grasp_type(current_grasp_type)) { @@ -89,20 +89,20 @@ bool SimTilburgHand::set_grasp_type(common::GraspType grasp_type) { return true; } -SimTilburgHandConfig *SimTilburgHand::get_config() { +SimTilburgHandConfig* SimTilburgHand::get_config() { // copy config to heap - SimTilburgHandConfig *cfg = new SimTilburgHandConfig(); + SimTilburgHandConfig* cfg = new SimTilburgHandConfig(); *cfg = this->cfg; return cfg; } -SimTilburgHandState *SimTilburgHand::get_state() { - SimTilburgHandState *state = new SimTilburgHandState(); +SimTilburgHandState* SimTilburgHand::get_state() { + SimTilburgHandState* state = new SimTilburgHandState(); *state = this->state; return state; } void SimTilburgHand::set_normalized_joint_poses( - const rcs::common::VectorXd &q) { + const rcs::common::VectorXd& q) { if (q.size() != this->n_joints) { throw std::invalid_argument("Invalid joint pose vector size, expected 16."); } diff --git a/src/sim/SimTilburgHand.h b/src/sim/SimTilburgHand.h index c100cde3..03f19f64 100644 --- a/src/sim/SimTilburgHand.h +++ b/src/sim/SimTilburgHand.h @@ -46,20 +46,20 @@ struct SimTilburgHandConfig : common::HandConfig { common::GraspType grasp_type = common::GraspType::POWER_GRASP; double seconds_between_callbacks = 0.0167; // 60 Hz - void add_id(const std::string &id) { - for (auto &s : this->collision_geoms) { + void add_id(const std::string& id) { + for (auto& s : this->collision_geoms) { s = s + "_" + id; } - for (auto &s : this->collision_geoms_fingers) { + for (auto& s : this->collision_geoms_fingers) { s = s + "_" + id; } - for (auto &s : this->ignored_collision_geoms) { + for (auto& s : this->ignored_collision_geoms) { s = s + "_" + id; } - for (auto &s : this->joints) { + for (auto& s : this->joints) { s = s + "_" + id; } - for (auto &s : this->actuators) { + for (auto& s : this->actuators) { s = s + "_" + id; } } @@ -85,8 +85,8 @@ class SimTilburgHand : public common::Hand { std::set cgeom; std::set cfgeom; std::set ignored_collision_geoms; - void add_collision_geoms(const std::vector &cgeoms_str, - std::set &cgeoms_set, bool clear_before); + void add_collision_geoms(const std::vector& cgeoms_str, + std::set& cgeoms_set, bool clear_before); void m_reset(); const rcs::common::VectorXd open_pose = @@ -100,17 +100,17 @@ class SimTilburgHand : public common::Hand { bool set_grasp_type(common::GraspType grasp_type); public: - SimTilburgHand(std::shared_ptr sim, const SimTilburgHandConfig &cfg); + SimTilburgHand(std::shared_ptr sim, const SimTilburgHandConfig& cfg); ~SimTilburgHand() override; - bool set_config(const SimTilburgHandConfig &cfg); + bool set_config(const SimTilburgHandConfig& cfg); - SimTilburgHandConfig *get_config() override; + SimTilburgHandConfig* get_config() override; - SimTilburgHandState *get_state() override; + SimTilburgHandState* get_state() override; // normalized joints of the hand, 0 is closed, 1 is open - void set_normalized_joint_poses(const rcs::common::VectorXd &q) override; + void set_normalized_joint_poses(const rcs::common::VectorXd& q) override; rcs::common::VectorXd get_normalized_joint_poses() override; void reset() override; From 955bd34b269a2cc9325823f793b5e5cb87f48307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20J=C3=BClg?= Date: Tue, 2 Dec 2025 16:44:46 +0100 Subject: [PATCH 08/16] ci: fix leftover - removed non existing zed extension - cmake policy: allow cmake version smaller than 3.5 - update main.cpp - fix cppsrc path in makefile of panda - removed clang tidy --- .github/workflows/extensions.yaml | 5 ++--- extensions/rcs_fr3/CMakeLists.txt | 1 + extensions/rcs_fr3/src/hw/main.cpp | 4 ++-- extensions/rcs_panda/Makefile | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/extensions.yaml b/.github/workflows/extensions.yaml index 6118bb73..5ac639a9 100644 --- a/.github/workflows/extensions.yaml +++ b/.github/workflows/extensions.yaml @@ -14,7 +14,6 @@ jobs: # - rcs_robotiq - rcs_tacto - rcs_usb_cam - - rcs_zed runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -74,8 +73,8 @@ jobs: pip install -r requirements.txt - name: Check clang format run: make -C extensions/${{ matrix.extension }} cppcheckformat - - name: Clang Tidy - run: make -C extensions/${{ matrix.extension }} cpplint + # - name: Clang Tidy + # run: make -C extensions/${{ matrix.extension }} cpplint - name: Clang build run: make -C extensions/${{ matrix.extension }} clangcompile PYTHON_EXECUTABLE=${{ steps.setup-python.outputs.python-path }} diff --git a/extensions/rcs_fr3/CMakeLists.txt b/extensions/rcs_fr3/CMakeLists.txt index 144dc57a..c6703ba9 100644 --- a/extensions/rcs_fr3/CMakeLists.txt +++ b/extensions/rcs_fr3/CMakeLists.txt @@ -25,6 +25,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_POLICY_VERSION_MINIMUM 3.5) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) diff --git a/extensions/rcs_fr3/src/hw/main.cpp b/extensions/rcs_fr3/src/hw/main.cpp index 6e0a4922..e1b46ed3 100644 --- a/extensions/rcs_fr3/src/hw/main.cpp +++ b/extensions/rcs_fr3/src/hw/main.cpp @@ -13,11 +13,11 @@ using namespace std; const string ip = "192.168.101.1"; -const string urdf_path = "models/urdf/fr3.urdf"; +const string mjcf_path = "assets/fr3/mjcf/fr3_0.xml"; int main() { try { - auto ik = make_shared(urdf_path); + auto ik = make_shared(mjcf_path, "attachment_site_0", false); rcs::hw::Franka robot(ip, ik); robot.automatic_error_recovery(); std::cout << "WARNING: This example will move the robot! " diff --git a/extensions/rcs_panda/Makefile b/extensions/rcs_panda/Makefile index 94c1bce0..20b02c8e 100644 --- a/extensions/rcs_panda/Makefile +++ b/extensions/rcs_panda/Makefile @@ -1,5 +1,5 @@ PYSRC = src/rcs_panda -CPPSRC = src +CPPSRC = src_fr3 COMPILE_MODE = Release # CPP From 733be6b6380b3088d93477af0cac703325397d88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20J=C3=BClg?= Date: Tue, 2 Dec 2025 17:55:05 +0100 Subject: [PATCH 09/16] ci: caching and dependent extensions --- .../workflows/{extensions.yaml => ci.yaml} | 129 +++++++++++++----- .github/workflows/cpp.yaml | 18 ++- .github/workflows/py.yaml | 45 ------ 3 files changed, 106 insertions(+), 86 deletions(-) rename .github/workflows/{extensions.yaml => ci.yaml} (51%) delete mode 100644 .github/workflows/py.yaml diff --git a/.github/workflows/extensions.yaml b/.github/workflows/ci.yaml similarity index 51% rename from .github/workflows/extensions.yaml rename to .github/workflows/ci.yaml index 5ac639a9..15697ec8 100644 --- a/.github/workflows/extensions.yaml +++ b/.github/workflows/ci.yaml @@ -1,10 +1,75 @@ -name: Extensions +name: Python on: workflow_call: + pull_request: + paths: + - "python/**" + - "src/pybind/**" + - ".github/workflows/py.yaml" + - "extensions/**" + push: + branches: + - master jobs: + pythonpackage: + runs-on: ubuntu-latest + env: + CC: clang + CXX: clang++ + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v4 + - name: Cache build directory + uses: actions/cache@v4 + with: + path: build + key: ${{ runner.os }}-build-py-${{ hashFiles('src/**', 'include/**', 'CMakeLists.txt', 'pyproject.toml') }} + restore-keys: | + ${{ runner.os }}-build-py- + - name: Install CPP dependencies + run: sudo apt install $(cat debian_deps.txt) + - name: Install virtual frame buffer tool + run: sudo apt install xvfb + - name: Set up Python 3.11 + uses: actions/setup-python@v5 + with: + python-version: "3.11" + cache: "pip" + - name: Install building dependencies + run: python -m pip install -r requirements.txt + - name: Install wheel + run: python -m pip install wheel + - name: Install the package + run: python -m pip install -v --no-build-isolation '.[dev]' + - name: Check formatting + run: make pycheckformat + - name: Code linting + run: make pylint + - name: Check that stub files are up-to-date + run: make stubgen && git diff --exit-code + - name: Ensure all unittests(pytest) are passing + run: xvfb-run make pytest + + check-paths: + runs-on: ubuntu-latest + outputs: + extensions_changed: ${{ steps.changed-files.outputs.any_changed }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Get changed files for extensions + id: changed-files + uses: tj-actions/changed-files@v41 + with: + files: | + extensions/** + build_extensions: + needs: [pythonpackage, check-paths] + if: needs.check-paths.outputs.extensions_changed == 'true' strategy: matrix: extension: @@ -24,6 +89,13 @@ jobs: key: ${{ runner.os }}-apt-${{ hashFiles('debian_deps.txt') }} restore-keys: | ${{ runner.os }}-apt- + - name: Cache rcs build directory + uses: actions/cache@v4 + with: + path: build + key: ${{ runner.os }}-build-py-${{ hashFiles('src/**', 'include/**', 'CMakeLists.txt', 'pyproject.toml') }} + restore-keys: | + ${{ runner.os }}-build-py- - name: Install dependencies run: sudo apt install $(cat debian_deps.txt) - name: Set up Python 3.11 @@ -42,7 +114,9 @@ jobs: - name: Install extension run: pip install -v --no-build-isolation extensions/${{ matrix.extension }} - build_cpp_extensions_clang: + build_cpp_extensions: + needs: [pythonpackage, check-paths] + if: needs.check-paths.outputs.extensions_changed == 'true' strategy: matrix: extension: @@ -60,42 +134,20 @@ jobs: key: ${{ runner.os }}-apt-${{ hashFiles('debian_deps.txt') }} restore-keys: | ${{ runner.os }}-apt- - - name: Install dependencies - run: sudo apt install $(cat debian_deps.txt) - - name: Set up Python 3.11 - id: setup-python - uses: actions/setup-python@v5 + - name: Cache rcs build directory + uses: actions/cache@v4 with: - python-version: "3.11" - cache: "pip" - - name: Install Python dependencies - run: | - pip install -r requirements.txt - - name: Check clang format - run: make -C extensions/${{ matrix.extension }} cppcheckformat - # - name: Clang Tidy - # run: make -C extensions/${{ matrix.extension }} cpplint - - name: Clang build - run: make -C extensions/${{ matrix.extension }} clangcompile PYTHON_EXECUTABLE=${{ steps.setup-python.outputs.python-path }} - - build_cpp_extensions_gcc: - strategy: - matrix: - extension: - - rcs_fr3 - - rcs_panda - - rcs_robotics_library - - rcs_so101 - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Cache apt packages + path: build + key: ${{ runner.os }}-build-py-${{ hashFiles('src/**', 'include/**', 'CMakeLists.txt', 'pyproject.toml') }} + restore-keys: | + ${{ runner.os }}-build-py- + - name: Cache extension build directory uses: actions/cache@v4 with: - path: /var/cache/apt/archives - key: ${{ runner.os }}-apt-${{ hashFiles('debian_deps.txt') }} + path: extensions/${{ matrix.extension }}/build + key: ${{ runner.os }}-build-ext-${{ matrix.extension }}-${{ hashFiles('extensions/${{ matrix.extension }}/**') }} restore-keys: | - ${{ runner.os }}-apt- + ${{ runner.os }}-build-ext-${{ matrix.extension }}- - name: Install dependencies run: sudo apt install $(cat debian_deps.txt) - name: Set up Python 3.11 @@ -109,8 +161,11 @@ jobs: pip install -r requirements.txt pip install -v --no-build-isolation '.[dev]' pip install -v --no-build-isolation extensions/${{ matrix.extension }} - - name: GCC build - run: make -C extensions/${{ matrix.extension }} gcccompile PYTHON_EXECUTABLE=${{ steps.setup-python.outputs.python-path }} - name: Check that stub files are up-to-date run: make -C extensions/${{ matrix.extension }} stubgen && git diff --exit-code - + - name: Clang build + run: make -C extensions/${{ matrix.extension }} clangcompile PYTHON_EXECUTABLE=${{ steps.setup-python.outputs.python-path }} + - name: Check clang format + run: make -C extensions/${{ matrix.extension }} cppcheckformat + # - name: Clang Tidy + # run: make -C extensions/${{ matrix.extension }} cpplint diff --git a/.github/workflows/cpp.yaml b/.github/workflows/cpp.yaml index d91afc5b..b6b1afb9 100644 --- a/.github/workflows/cpp.yaml +++ b/.github/workflows/cpp.yaml @@ -5,7 +5,6 @@ on: paths: - "src/**" - "include/**" - - "extensions/**" - ".github/workflows/cpp.yaml" push: branches: @@ -23,6 +22,13 @@ jobs: key: ${{ runner.os }}-apt-${{ hashFiles('debian_deps.txt') }} restore-keys: | ${{ runner.os }}-apt- + - name: Cache build directory + uses: actions/cache@v4 + with: + path: build + key: ${{ runner.os }}-build-cpp-${{ hashFiles('src/**', 'include/**', 'CMakeLists.txt', 'pyproject.toml') }} + restore-keys: | + ${{ runner.os }}-build-cpp- - name: Install dependencies run: sudo apt install $(cat debian_deps.txt) - name: Set up Python 3.11 @@ -52,6 +58,13 @@ jobs: key: ${{ runner.os }}-apt-${{ hashFiles('debian_deps.txt') }} restore-keys: | ${{ runner.os }}-apt- + - name: Cache build directory + uses: actions/cache@v4 + with: + path: build + key: ${{ runner.os }}-build-cpp-${{ hashFiles('src/**', 'include/**', 'CMakeLists.txt', 'pyproject.toml') }} + restore-keys: | + ${{ runner.os }}-build-cpp- - name: Install dependencies run: sudo apt install $(cat debian_deps.txt) - name: Set up Python 3.11 @@ -66,6 +79,3 @@ jobs: - name: GCC build run: make gcccompile PYTHON_EXECUTABLE=${{ steps.setup-python.outputs.python-path }} - build_extensions: - needs: [build_clang, build_gcc] - uses: ./.github/workflows/extensions.yaml diff --git a/.github/workflows/py.yaml b/.github/workflows/py.yaml deleted file mode 100644 index 40a18c07..00000000 --- a/.github/workflows/py.yaml +++ /dev/null @@ -1,45 +0,0 @@ -name: Python -on: - workflow_call: - pull_request: - paths: - - "python/**" - - "src/pybind/**" - - ".github/workflows/py.yaml" - push: - branches: - - master - -jobs: - pythonpackage: - needs: format - runs-on: ubuntu-latest - env: - CC: clang - CXX: clang++ - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - uses: actions/checkout@v4 - - name: Install CPP dependencies - run: sudo apt install $(cat debian_deps.txt) - - name: Install virtual frame buffer tool - run: sudo apt install xvfb - - name: Set up Python 3.11 - uses: actions/setup-python@v5 - with: - python-version: "3.11" - cache: "pip" - - name: Install building dependencies - run: python -m pip install -r requirements.txt - - name: Install wheel - run: python -m pip install wheel - - name: Install the package - run: python -m pip install -v --no-build-isolation '.[dev]' - - name: Check formatting - run: make pycheckformat - - name: Code linting - run: make pylint - - name: Check that stub files are up-to-date - run: make stubgen && git diff --exit-code - - name: Ensure all unittests(pytest) are passing - run: xvfb-run make pytest From 593111d8435056b85b0724db06a6020e7fb763ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20J=C3=BClg?= Date: Tue, 2 Dec 2025 18:23:45 +0100 Subject: [PATCH 10/16] fix: replaced apriltags with pupil_apriltags --- .github/workflows/cpp.yaml | 7 --- extensions/rcs_panda/CMakeLists.txt | 1 + extensions/rcs_realsense/pyproject.toml | 2 +- .../src/rcs_realsense/calibration.py | 43 +++++++++---------- 4 files changed, 23 insertions(+), 30 deletions(-) diff --git a/.github/workflows/cpp.yaml b/.github/workflows/cpp.yaml index b6b1afb9..a101a124 100644 --- a/.github/workflows/cpp.yaml +++ b/.github/workflows/cpp.yaml @@ -22,13 +22,6 @@ jobs: key: ${{ runner.os }}-apt-${{ hashFiles('debian_deps.txt') }} restore-keys: | ${{ runner.os }}-apt- - - name: Cache build directory - uses: actions/cache@v4 - with: - path: build - key: ${{ runner.os }}-build-cpp-${{ hashFiles('src/**', 'include/**', 'CMakeLists.txt', 'pyproject.toml') }} - restore-keys: | - ${{ runner.os }}-build-cpp- - name: Install dependencies run: sudo apt install $(cat debian_deps.txt) - name: Set up Python 3.11 diff --git a/extensions/rcs_panda/CMakeLists.txt b/extensions/rcs_panda/CMakeLists.txt index 7f1e14bc..31806b12 100644 --- a/extensions/rcs_panda/CMakeLists.txt +++ b/extensions/rcs_panda/CMakeLists.txt @@ -25,6 +25,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_POLICY_VERSION_MINIMUM 3.5) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) diff --git a/extensions/rcs_realsense/pyproject.toml b/extensions/rcs_realsense/pyproject.toml index 709e5159..e6413409 100644 --- a/extensions/rcs_realsense/pyproject.toml +++ b/extensions/rcs_realsense/pyproject.toml @@ -9,7 +9,7 @@ description="RCS realsense module" dependencies = [ "rcs>=0.5.0", "pyrealsense2~=2.55.1", - "apriltag==0.0.16", + "pupil_apriltags", "diskcache", ] maintainers = [ diff --git a/extensions/rcs_realsense/src/rcs_realsense/calibration.py b/extensions/rcs_realsense/src/rcs_realsense/calibration.py index 647419bb..c853f45a 100644 --- a/extensions/rcs_realsense/src/rcs_realsense/calibration.py +++ b/extensions/rcs_realsense/src/rcs_realsense/calibration.py @@ -4,10 +4,10 @@ from pathlib import Path from time import sleep -import apriltag import cv2 import diskcache as dc import numpy as np +from pupil_apriltags import Detector from rcs._core import common from rcs.camera.hw import CalibrationStrategy from rcs.camera.interface import Frame @@ -40,7 +40,7 @@ def calibrate( input() tries = 3 while len(samples) < 10 and tries > 0: - logger.info("not enought frames in recorded, waiting 2 seconds...") + logger.info("not enough frames in recorded, waiting 2 seconds...") tries = -1 sleep(2) if tries == 0: @@ -51,7 +51,7 @@ def calibrate( with lock: for sample in samples: frames.append(sample.camera.color.data.copy()) - print(frames) + # print(frames) # Removed print for cleaner logs, optional _, tag_to_cam = get_average_marker_pose(frames, intrinsics=intrinsics, calib_tag_id=9, show_live_window=False) @@ -71,9 +71,9 @@ def get_average_marker_pose( calib_tag_id, show_live_window, ): - # create detector - options = apriltag.DetectorOptions(families="tag25h9") - detector = apriltag.Detector(options=options) + # CHANGE 2: Simplified Initialization + # No "DetectorOptions" object needed anymore. + detector = Detector(families="tag25h9") # make while loop with tqdm poses = [] @@ -97,6 +97,7 @@ def get_average_marker_pose( camera_matrix = intrinsics[:3, :3] if show_live_window: + # Note: pose[:3, :3] works because we construct the 4x4 matrix in get_marker_pose below cv2.drawFrameAxes(frame, camera_matrix, None, pose[:3, :3], pose[:3, 3], 0.1) # type: ignore # show frame cv2.imshow("frame", frame) @@ -120,7 +121,15 @@ def get_average_marker_pose( def get_marker_pose(calib_tag_id, detector, intrinsics, frame): gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) - detections = detector.detect(gray) + + # CHANGE 3: Pose estimation happens INSIDE .detect() + # We must extract camera params first to pass them here + fx = intrinsics[0, 0] + fy = intrinsics[1, 1] + cx = intrinsics[0, 2] + cy = intrinsics[1, 2] + + detections = detector.detect(gray, estimate_tag_pose=True, camera_params=[fx, fy, cx, cy], tag_size=0.1) # count detections n_det = 0 @@ -138,20 +147,10 @@ def get_marker_pose(calib_tag_id, detector, intrinsics, frame): if marker_det is None: return None, None - fx = intrinsics[0, 0] - fy = intrinsics[1, 1] - cx = intrinsics[0, 2] - cy = intrinsics[1, 2] - - pose, _, _ = detector.detection_pose( - marker_det, - camera_params=( - fx, - fy, - cx, - cy, - ), - tag_size=0.1, - ) + # CHANGE 4: Construct 4x4 Matrix manually + # pupil-apriltags gives us R (3x3) and t (3x1). We must stack them. + pose = np.eye(4) + pose[:3, :3] = marker_det.pose_R + pose[:3, 3] = marker_det.pose_t.ravel() # ravel() flattens the (3,1) array to (3,) return marker_det, pose From d040064691ada6e174d4d472b04432c103a687c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20J=C3=BClg?= Date: Tue, 2 Dec 2025 18:54:22 +0100 Subject: [PATCH 11/16] ci: add xvfb for stubgen --- .github/workflows/ci.yaml | 4 +++- extensions/rcs_fr3/src/rcs_fr3/_core/hw/__init__.pyi | 9 ++------- extensions/rcs_panda/src/rcs_panda/_core/hw/__init__.pyi | 9 ++------- extensions/rcs_robotics_library/CMakeLists.txt | 1 + 4 files changed, 8 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 15697ec8..4783e732 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -134,6 +134,8 @@ jobs: key: ${{ runner.os }}-apt-${{ hashFiles('debian_deps.txt') }} restore-keys: | ${{ runner.os }}-apt- + - name: Install virtual frame buffer tool + run: sudo apt install xvfb - name: Cache rcs build directory uses: actions/cache@v4 with: @@ -162,7 +164,7 @@ jobs: pip install -v --no-build-isolation '.[dev]' pip install -v --no-build-isolation extensions/${{ matrix.extension }} - name: Check that stub files are up-to-date - run: make -C extensions/${{ matrix.extension }} stubgen && git diff --exit-code + run: xvfb-run make -C extensions/${{ matrix.extension }} stubgen && git diff --exit-code - name: Clang build run: make -C extensions/${{ matrix.extension }} clangcompile PYTHON_EXECUTABLE=${{ steps.setup-python.outputs.python-path }} - name: Check clang format diff --git a/extensions/rcs_fr3/src/rcs_fr3/_core/hw/__init__.pyi b/extensions/rcs_fr3/src/rcs_fr3/_core/hw/__init__.pyi index 9f3b01f2..006e7e50 100644 --- a/extensions/rcs_fr3/src/rcs_fr3/_core/hw/__init__.pyi +++ b/extensions/rcs_fr3/src/rcs_fr3/_core/hw/__init__.pyi @@ -57,19 +57,14 @@ class Franka(rcs._core.common.Robot): def __init__(self, ip: str, ik: rcs._core.common.Kinematics | None = None) -> None: ... def automatic_error_recovery(self) -> None: ... def controller_set_joint_position( - self, - desired_q: numpy.ndarray[tuple[typing.Literal[7]], numpy.dtype[numpy.float64]], + self, desired_q: numpy.ndarray[tuple[typing.Literal[7]], numpy.dtype[numpy.float64]] ) -> None: ... def double_tap_robot_to_continue(self) -> None: ... def get_config(self) -> FrankaConfig: ... def get_state(self) -> FrankaState: ... def osc_set_cartesian_position(self, desired_pos_EE_in_base_frame: rcs._core.common.Pose) -> None: ... def set_cartesian_position_ik( - self, - pose: rcs._core.common.Pose, - max_time: float, - elbow: float | None, - max_force: float | None = 5, + self, pose: rcs._core.common.Pose, max_time: float, elbow: float | None, max_force: float | None = 5 ) -> None: ... def set_cartesian_position_internal(self, pose: rcs._core.common.Pose) -> None: ... def set_config(self, cfg: FrankaConfig) -> bool: ... diff --git a/extensions/rcs_panda/src/rcs_panda/_core/hw/__init__.pyi b/extensions/rcs_panda/src/rcs_panda/_core/hw/__init__.pyi index 9f3b01f2..006e7e50 100644 --- a/extensions/rcs_panda/src/rcs_panda/_core/hw/__init__.pyi +++ b/extensions/rcs_panda/src/rcs_panda/_core/hw/__init__.pyi @@ -57,19 +57,14 @@ class Franka(rcs._core.common.Robot): def __init__(self, ip: str, ik: rcs._core.common.Kinematics | None = None) -> None: ... def automatic_error_recovery(self) -> None: ... def controller_set_joint_position( - self, - desired_q: numpy.ndarray[tuple[typing.Literal[7]], numpy.dtype[numpy.float64]], + self, desired_q: numpy.ndarray[tuple[typing.Literal[7]], numpy.dtype[numpy.float64]] ) -> None: ... def double_tap_robot_to_continue(self) -> None: ... def get_config(self) -> FrankaConfig: ... def get_state(self) -> FrankaState: ... def osc_set_cartesian_position(self, desired_pos_EE_in_base_frame: rcs._core.common.Pose) -> None: ... def set_cartesian_position_ik( - self, - pose: rcs._core.common.Pose, - max_time: float, - elbow: float | None, - max_force: float | None = 5, + self, pose: rcs._core.common.Pose, max_time: float, elbow: float | None, max_force: float | None = 5 ) -> None: ... def set_cartesian_position_internal(self, pose: rcs._core.common.Pose) -> None: ... def set_config(self, cfg: FrankaConfig) -> bool: ... diff --git a/extensions/rcs_robotics_library/CMakeLists.txt b/extensions/rcs_robotics_library/CMakeLists.txt index d3d2526e..4b91c491 100644 --- a/extensions/rcs_robotics_library/CMakeLists.txt +++ b/extensions/rcs_robotics_library/CMakeLists.txt @@ -25,6 +25,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_POLICY_VERSION_MINIMUM 3.5) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) From 9957f2f6baa53d33569e5b1982a7ffdf45c2b5cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20J=C3=BClg?= Date: Tue, 2 Dec 2025 19:30:44 +0100 Subject: [PATCH 12/16] ci: install debian_deps.txt if the file exists --- .github/workflows/ci.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 4783e732..248f2ef0 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -136,6 +136,11 @@ jobs: ${{ runner.os }}-apt- - name: Install virtual frame buffer tool run: sudo apt install xvfb + - name: Install potential debian deps + run: | + if [ -f extensions/${{ matrix.extension }}/debian_deps.txt ]; then + sudo apt install $(cat extensions/${{ matrix.extension }}/debian_deps.txt) + fi - name: Cache rcs build directory uses: actions/cache@v4 with: From 152e40c9f7c50a6474c7b77851dcbe1f437244fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20J=C3=BClg?= Date: Wed, 3 Dec 2025 03:48:32 +0100 Subject: [PATCH 13/16] ci: fix stubgen by removing gym import --- .github/workflows/ci.yaml | 2 +- extensions/rcs_fr3/src/rcs_fr3/__init__.py | 10 ++++++++-- extensions/rcs_panda/src/rcs_panda/__init__.py | 10 ++++++++-- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 248f2ef0..90db0f49 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -169,7 +169,7 @@ jobs: pip install -v --no-build-isolation '.[dev]' pip install -v --no-build-isolation extensions/${{ matrix.extension }} - name: Check that stub files are up-to-date - run: xvfb-run make -C extensions/${{ matrix.extension }} stubgen && git diff --exit-code + run: make -C extensions/${{ matrix.extension }} stubgen && git diff --exit-code - name: Clang build run: make -C extensions/${{ matrix.extension }} clangcompile PYTHON_EXECUTABLE=${{ steps.setup-python.outputs.python-path }} - name: Check clang format diff --git a/extensions/rcs_fr3/src/rcs_fr3/__init__.py b/extensions/rcs_fr3/src/rcs_fr3/__init__.py index 29e879ce..30b19b08 100644 --- a/extensions/rcs_fr3/src/rcs_fr3/__init__.py +++ b/extensions/rcs_fr3/src/rcs_fr3/__init__.py @@ -1,8 +1,14 @@ -from rcs_fr3 import desk, envs +import sys + +from rcs_fr3 import desk from rcs_fr3._core import hw __all__ = [ "desk", - "envs", "hw", ] + +if "pybind11_stubgen" not in sys.modules: + from rcs_panda import envs # noqa: F401 + + __all__.append("envs") diff --git a/extensions/rcs_panda/src/rcs_panda/__init__.py b/extensions/rcs_panda/src/rcs_panda/__init__.py index 0601967b..66f52fcb 100644 --- a/extensions/rcs_panda/src/rcs_panda/__init__.py +++ b/extensions/rcs_panda/src/rcs_panda/__init__.py @@ -1,7 +1,13 @@ -from rcs_panda import envs +import sys + from rcs_panda._core import hw __all__ = [ - "envs", "hw", ] + +# prevent gymnasium import during stubgen, which can cause a segfault +if "pybind11_stubgen" not in sys.modules: + from rcs_panda import envs # noqa: F401 + + __all__.append("envs") From 5e82da25c8037aa81d072fac3afa76f3cfe509cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20J=C3=BClg?= Date: Wed, 3 Dec 2025 11:59:53 +0100 Subject: [PATCH 14/16] ci: undo build caching --- .github/workflows/ci.yaml | 28 ---------------------------- .github/workflows/cpp.yaml | 7 ------- 2 files changed, 35 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 90db0f49..4b0f9a19 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -21,13 +21,6 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - uses: actions/checkout@v4 - - name: Cache build directory - uses: actions/cache@v4 - with: - path: build - key: ${{ runner.os }}-build-py-${{ hashFiles('src/**', 'include/**', 'CMakeLists.txt', 'pyproject.toml') }} - restore-keys: | - ${{ runner.os }}-build-py- - name: Install CPP dependencies run: sudo apt install $(cat debian_deps.txt) - name: Install virtual frame buffer tool @@ -89,13 +82,6 @@ jobs: key: ${{ runner.os }}-apt-${{ hashFiles('debian_deps.txt') }} restore-keys: | ${{ runner.os }}-apt- - - name: Cache rcs build directory - uses: actions/cache@v4 - with: - path: build - key: ${{ runner.os }}-build-py-${{ hashFiles('src/**', 'include/**', 'CMakeLists.txt', 'pyproject.toml') }} - restore-keys: | - ${{ runner.os }}-build-py- - name: Install dependencies run: sudo apt install $(cat debian_deps.txt) - name: Set up Python 3.11 @@ -141,20 +127,6 @@ jobs: if [ -f extensions/${{ matrix.extension }}/debian_deps.txt ]; then sudo apt install $(cat extensions/${{ matrix.extension }}/debian_deps.txt) fi - - name: Cache rcs build directory - uses: actions/cache@v4 - with: - path: build - key: ${{ runner.os }}-build-py-${{ hashFiles('src/**', 'include/**', 'CMakeLists.txt', 'pyproject.toml') }} - restore-keys: | - ${{ runner.os }}-build-py- - - name: Cache extension build directory - uses: actions/cache@v4 - with: - path: extensions/${{ matrix.extension }}/build - key: ${{ runner.os }}-build-ext-${{ matrix.extension }}-${{ hashFiles('extensions/${{ matrix.extension }}/**') }} - restore-keys: | - ${{ runner.os }}-build-ext-${{ matrix.extension }}- - name: Install dependencies run: sudo apt install $(cat debian_deps.txt) - name: Set up Python 3.11 diff --git a/.github/workflows/cpp.yaml b/.github/workflows/cpp.yaml index a101a124..edf659ff 100644 --- a/.github/workflows/cpp.yaml +++ b/.github/workflows/cpp.yaml @@ -51,13 +51,6 @@ jobs: key: ${{ runner.os }}-apt-${{ hashFiles('debian_deps.txt') }} restore-keys: | ${{ runner.os }}-apt- - - name: Cache build directory - uses: actions/cache@v4 - with: - path: build - key: ${{ runner.os }}-build-cpp-${{ hashFiles('src/**', 'include/**', 'CMakeLists.txt', 'pyproject.toml') }} - restore-keys: | - ${{ runner.os }}-build-cpp- - name: Install dependencies run: sudo apt install $(cat debian_deps.txt) - name: Set up Python 3.11 From 2266d1ec5abcad273fa78f6fcc5ebfa8e58bfe22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20J=C3=BClg?= Date: Wed, 3 Dec 2025 12:14:18 +0100 Subject: [PATCH 15/16] ci: extensions remove clang build --- .github/workflows/ci.yaml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 4b0f9a19..16f2ba14 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -136,15 +136,16 @@ jobs: python-version: "3.11" cache: "pip" - name: Install Python dependencies - run: | - pip install -r requirements.txt - pip install -v --no-build-isolation '.[dev]' - pip install -v --no-build-isolation extensions/${{ matrix.extension }} + run: pip install -r requirements.txt + - name: Install RCS + run: pip install -v --no-build-isolation '.[dev]' + - name: Install extension + run: pip install -v --no-build-isolation extensions/${{ matrix.extension }} - name: Check that stub files are up-to-date run: make -C extensions/${{ matrix.extension }} stubgen && git diff --exit-code - - name: Clang build - run: make -C extensions/${{ matrix.extension }} clangcompile PYTHON_EXECUTABLE=${{ steps.setup-python.outputs.python-path }} - name: Check clang format run: make -C extensions/${{ matrix.extension }} cppcheckformat # - name: Clang Tidy # run: make -C extensions/${{ matrix.extension }} cpplint + # - name: Clang build + # run: make -C extensions/${{ matrix.extension }} clangcompile PYTHON_EXECUTABLE=${{ steps.setup-python.outputs.python-path }} From f4e831242f6e4f3af8cfa32190fe67afbbc9793e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20J=C3=BClg?= Date: Wed, 3 Dec 2025 08:33:12 +0100 Subject: [PATCH 16/16] style: fix cpp format --- extensions/rcs_fr3/src/hw/main.cpp | 3 ++- extensions/rcs_robotics_library/src/pybind/rcs.cpp | 2 +- .../src/rcs_robotics_library/__init__.pyi | 5 ----- .../src/rcs_robotics_library/_core/__init__.pyi | 2 +- .../src/rcs_robotics_library/_core/rl.pyi | 2 +- 5 files changed, 5 insertions(+), 9 deletions(-) delete mode 100644 extensions/rcs_robotics_library/src/rcs_robotics_library/__init__.pyi diff --git a/extensions/rcs_fr3/src/hw/main.cpp b/extensions/rcs_fr3/src/hw/main.cpp index e1b46ed3..4873e726 100644 --- a/extensions/rcs_fr3/src/hw/main.cpp +++ b/extensions/rcs_fr3/src/hw/main.cpp @@ -17,7 +17,8 @@ const string mjcf_path = "assets/fr3/mjcf/fr3_0.xml"; int main() { try { - auto ik = make_shared(mjcf_path, "attachment_site_0", false); + auto ik = + make_shared(mjcf_path, "attachment_site_0", false); rcs::hw::Franka robot(ip, ik); robot.automatic_error_recovery(); std::cout << "WARNING: This example will move the robot! " diff --git a/extensions/rcs_robotics_library/src/pybind/rcs.cpp b/extensions/rcs_robotics_library/src/pybind/rcs.cpp index 8efaa951..094daab7 100644 --- a/extensions/rcs_robotics_library/src/pybind/rcs.cpp +++ b/extensions/rcs_robotics_library/src/pybind/rcs.cpp @@ -42,6 +42,6 @@ PYBIND11_MODULE(_core, m) { py::class_>( rl, "RoboticsLibraryIK", kinematics) - .def(py::init(), py::arg("urdf_path"), + .def(py::init(), py::arg("urdf_path"), py::arg("max_duration_ms") = 300); } diff --git a/extensions/rcs_robotics_library/src/rcs_robotics_library/__init__.pyi b/extensions/rcs_robotics_library/src/rcs_robotics_library/__init__.pyi deleted file mode 100644 index 97237dac..00000000 --- a/extensions/rcs_robotics_library/src/rcs_robotics_library/__init__.pyi +++ /dev/null @@ -1,5 +0,0 @@ -from __future__ import annotations - -from rcs_robotics_library._core import rl - -__all__: list = ["rl"] diff --git a/extensions/rcs_robotics_library/src/rcs_robotics_library/_core/__init__.pyi b/extensions/rcs_robotics_library/src/rcs_robotics_library/_core/__init__.pyi index 173d1555..34e7cb68 100644 --- a/extensions/rcs_robotics_library/src/rcs_robotics_library/_core/__init__.pyi +++ b/extensions/rcs_robotics_library/src/rcs_robotics_library/_core/__init__.pyi @@ -1,3 +1,4 @@ +# ATTENTION: auto generated from C++ code, use `make stubgen` to update! """ Robot Control Stack Python Bindings @@ -10,7 +11,6 @@ """ - from __future__ import annotations from . import rl diff --git a/extensions/rcs_robotics_library/src/rcs_robotics_library/_core/rl.pyi b/extensions/rcs_robotics_library/src/rcs_robotics_library/_core/rl.pyi index 4c4b0afb..d0001745 100644 --- a/extensions/rcs_robotics_library/src/rcs_robotics_library/_core/rl.pyi +++ b/extensions/rcs_robotics_library/src/rcs_robotics_library/_core/rl.pyi @@ -1,7 +1,7 @@ +# ATTENTION: auto generated from C++ code, use `make stubgen` to update! """ rcs robotics library module """ - from __future__ import annotations import rcs._core.common