diff --git a/.github/actions/build-test-protocol/Dockerfile b/.github/actions/build-test-protocol/Dockerfile deleted file mode 100644 index fb4062ea0..000000000 --- a/.github/actions/build-test-protocol/Dockerfile +++ /dev/null @@ -1,5 +0,0 @@ -FROM ghcr.io/aica-technology/control-libraries/development-dependencies:latest - -# Copy and set the entrypoint commands to execute when the container starts -COPY entrypoint.sh /entrypoint.sh -ENTRYPOINT ["/entrypoint.sh"] diff --git a/.github/actions/build-test-protocol/action.yml b/.github/actions/build-test-protocol/action.yml deleted file mode 100644 index 134a24e6f..000000000 --- a/.github/actions/build-test-protocol/action.yml +++ /dev/null @@ -1,5 +0,0 @@ -name: 'Build and Test Protocol' -description: 'Build the protobuf message libraries and run all unit tests' -runs: - using: 'docker' - image: 'Dockerfile' \ No newline at end of file diff --git a/.github/actions/build-test-protocol/entrypoint.sh b/.github/actions/build-test-protocol/entrypoint.sh deleted file mode 100755 index 81b86e807..000000000 --- a/.github/actions/build-test-protocol/entrypoint.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/sh -l - -echo ">>> Installing control libraries..." -bash /github/workspace/source/install.sh --auto --no-controllers --no-dynamical-systems --no-robot-model || exit 1 -ldconfig - -echo ">>> Building proto bindings..." -cd /github/workspace/protocol/protobuf && make all || exit 2 - -echo ">>> Configuring clproto_cpp cmake..." -cd /github/workspace/protocol/clproto_cpp && mkdir build && cd build \ - && cmake -DCMAKE_BUILD_TYPE=RELEASE -DBUILD_TESTING=ON .. \ - || (echo ">>> [ERROR] Configuration stage failed!" && exit 3) || exit $? - -echo ">>> Building clproto_cpp..." -make all || (echo ">>> [ERROR] Build stage failed!" && exit 4) || exit $? -echo ">>> Build stage completed successfully!" - -echo ">>> Running all test stages..." -CTEST_OUTPUT_ON_FAILURE=1 make test || (echo ">>> [ERROR] Test stage failed!" && exit 5) || exit $? -echo ">>> Test stages completed successfully!" - -exit 0 \ No newline at end of file diff --git a/.github/actions/build-test-python/Dockerfile b/.github/actions/build-test-python/Dockerfile deleted file mode 100644 index fb4062ea0..000000000 --- a/.github/actions/build-test-python/Dockerfile +++ /dev/null @@ -1,5 +0,0 @@ -FROM ghcr.io/aica-technology/control-libraries/development-dependencies:latest - -# Copy and set the entrypoint commands to execute when the container starts -COPY entrypoint.sh /entrypoint.sh -ENTRYPOINT ["/entrypoint.sh"] diff --git a/.github/actions/build-test-python/action.yml b/.github/actions/build-test-python/action.yml deleted file mode 100644 index e2d0133f2..000000000 --- a/.github/actions/build-test-python/action.yml +++ /dev/null @@ -1,5 +0,0 @@ -name: 'Build and Test Python' -description: 'Build the python bindings and run all unit tests' -runs: - using: 'docker' - image: 'Dockerfile' diff --git a/.github/actions/build-test-python/entrypoint.sh b/.github/actions/build-test-python/entrypoint.sh deleted file mode 100755 index 23022a820..000000000 --- a/.github/actions/build-test-python/entrypoint.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh -l - -echo ">>> Installing control libraries..." -bash /github/workspace/source/install.sh --auto || exit 1 -bash /github/workspace/protocol/install.sh --auto || exit 1 - -echo ">>> Building Python bindings..." - -export OSQP_INCLUDE_DIR='/usr/local/include/osqp' -pip3 install /github/workspace/python || (echo ">>> [ERROR] Build stage failed!" && exit 2) || exit $? - -echo ">>> Running all test stages..." -pytest /github/workspace/python -v || (echo ">>> [ERROR] Test stage failed!" && exit 3) || exit $? - -echo ">>> Test stages completed successfully!" - -exit 0 \ No newline at end of file diff --git a/.github/actions/build-test/Dockerfile b/.github/actions/build-test/Dockerfile deleted file mode 100644 index fb4062ea0..000000000 --- a/.github/actions/build-test/Dockerfile +++ /dev/null @@ -1,5 +0,0 @@ -FROM ghcr.io/aica-technology/control-libraries/development-dependencies:latest - -# Copy and set the entrypoint commands to execute when the container starts -COPY entrypoint.sh /entrypoint.sh -ENTRYPOINT ["/entrypoint.sh"] diff --git a/.github/actions/build-test/action.yml b/.github/actions/build-test/action.yml deleted file mode 100644 index 0ff45aa08..000000000 --- a/.github/actions/build-test/action.yml +++ /dev/null @@ -1,12 +0,0 @@ -name: 'Build and Test' -description: 'Build the project sources and run all unit tests' -inputs: - configuration: - description: 'CMake build configuration' - required: false - default: '' -runs: - using: 'docker' - image: 'Dockerfile' - args: - - ${{ inputs.configuration }} \ No newline at end of file diff --git a/.github/actions/build-test/entrypoint.sh b/.github/actions/build-test/entrypoint.sh deleted file mode 100755 index 1c7f24aa7..000000000 --- a/.github/actions/build-test/entrypoint.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh -l - -CONFIGURATION="" -if [ -n "$1" ]; then - echo ">>> Configuration: $1" - CONFIGURATION="-DCMAKE_BUILD_TYPE=$1" -fi - -cd /github/workspace/source && mkdir build && cd build || exit 1 - -echo ">>> Configuring cmake..." -cmake "${CONFIGURATION}" -DBUILD_TESTING=ON \ - -DBUILD_CONTROLLERS=ON -DBUILD_DYNAMICAL_SYSTEMS=ON -DBUILD_ROBOT_MODEL=ON .. || \ - (echo ">>> [ERROR] Configuration stage failed!" && exit 2) || exit $? - -echo ">>> Building project..." -make -j all || (echo ">>> [ERROR] Build stage failed!" && exit 3) || exit $? -echo ">>> Build stage completed successfully!" - -echo ">>> Running all test stages..." -CTEST_OUTPUT_ON_FAILURE=1 make test || (echo ">>> [ERROR] Test stage failed!" && exit 4) || exit $? -echo ">>> Test stages completed successfully!" - -exit 0 \ No newline at end of file diff --git a/.github/workflows/build-push.yml b/.github/workflows/build-push.yml deleted file mode 100644 index cd567e6f6..000000000 --- a/.github/workflows/build-push.yml +++ /dev/null @@ -1,57 +0,0 @@ -name: Build and Push - -# Run workflow on pushes to main branch or by manual dispatch -on: - push: - branches: - - main - workflow_dispatch: - -jobs: - build-publish-proto-dependencies-focal-fossa: - name: Build and publish proto dependencies image on ubuntu 20.04 - uses: aica-technology/.github/.github/workflows/build-push-multi-arch.yml@v0.1 - with: - image_name: ${{ github.repository }}/proto-dependencies - image_tags: 20.04 - dockerfile_path: Dockerfile.proto - platforms: linux/amd64 - build_flags: '--build-arg BASE_TAG=20.04' - secrets: - token: ${{ secrets.GITHUB_TOKEN }} - - build-publish-proto-dependencies-jammy-jellyfish: - name: Build and publish proto dependencies image on ubuntu 22.04 - uses: aica-technology/.github/.github/workflows/build-push-multi-arch.yml@v0.1 - with: - image_name: ${{ github.repository }}/proto-dependencies - image_tags: 22.04,latest - platforms: linux/amd64,linux/arm64 - dockerfile_path: Dockerfile.proto - build_flags: '--build-arg BASE_TAG=22.04' - secrets: - token: ${{ secrets.GITHUB_TOKEN }} - - build-publish-development-dependencies-focal-fossa: - needs: build-publish-proto-dependencies-focal-fossa - uses: aica-technology/.github/.github/workflows/build-push-multi-arch.yml@v0.1 - with: - image_name: ${{ github.repository }}/development-dependencies - image_tags: 20.04 - platforms: linux/amd64 - dockerfile_path: Dockerfile.base - build_flags: '--build-arg BASE_TAG=20.04' - secrets: - token: ${{ secrets.GITHUB_TOKEN }} - - build-publish-development-dependencies-jammy-jellyfish: - needs: build-publish-proto-dependencies-jammy-jellyfish - uses: aica-technology/.github/.github/workflows/build-push-multi-arch.yml@v0.1 - with: - image_name: ${{ github.repository }}/development-dependencies - image_tags: 22.04,latest - platforms: linux/amd64,linux/arm64 - dockerfile_path: Dockerfile.base - build_flags: '--build-arg BASE_TAG=22.04' - secrets: - token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/build-release.yaml b/.github/workflows/build-release.yaml deleted file mode 100644 index 95ec0513f..000000000 --- a/.github/workflows/build-release.yaml +++ /dev/null @@ -1,62 +0,0 @@ -name: Build and Push Multi-Arch Images - -on: - push: - branches: - - develop - - main - tags: - - "v*.*.*" - -jobs: - get-tag: - runs-on: ubuntu-latest - name: Get tag - outputs: - tag: ${{ steps.parse-tag.outputs.tag }} - steps: - - uses: actions/checkout@v3 - - uses: aica-technology/.github/.github/actions/docker-tag-from-git@v0.6.1 - id: parse-tag - - build: - needs: [get-tag] - strategy: - matrix: - arch: [amd64, arm64] - include: - - image: ubuntu-latest - # FIXME: using 4vcpu image because of heavy RAM usage when building pinoccio on arm64 - - image: buildjet-4vcpu-ubuntu-2204-arm - arch: arm64 - - runs-on: ${{ matrix.image }} - name: Build and publish (${{ matrix.arch }}) - steps: - - uses: actions/checkout@v3 - - - uses: aica-technology/.github/.github/actions/list-add-suffixes@v0.6.1 - id: merge-tags - with: - list: ${{ needs.get-tag.outputs.tag }} - suffixes: ${{ matrix.arch }} - glue_separator: "-" - - - uses: aica-technology/.github/.github/actions/ghcr-build@v0.6.1 - with: - image_name: aica-technology/control-libraries - image_tags: ${{ steps.merge-tags.outputs.list }} - dockerfile_path: Dockerfile - token: ${{ secrets.GITHUB_TOKEN }} - - multi-arch: - runs-on: ubuntu-latest - name: Merge into a multi-arch image - needs: [get-tag, build] - steps: - - uses: aica-technology/.github/.github/actions/ghcr-manifest-merge@v0.6.1 - with: - image_name: aica-technology/control-libraries - image_tags: ${{ needs.get-tag.outputs.tag }} - archs: amd64,arm64 - token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml new file mode 100644 index 000000000..69f1ff0ac --- /dev/null +++ b/.github/workflows/build-release.yml @@ -0,0 +1,107 @@ +name: Build and Push Multi-Arch Images + +on: + push: + branches: + - main + +jobs: + check-version: + name: Check if the version has been updated + outputs: + has_changed: ${{ steps.check.outputs.has_changed }} + version: ${{ steps.versions.outputs.new_version }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 2 + - id: versions + run: | + PREV_VERSION=$(git show HEAD^:VERSION) + NEW_VERSION=$(git show HEAD:VERSION) + echo "prev_version=${PREV_VERSION}" >> $GITHUB_OUTPUT + echo "new_version=${NEW_VERSION}" >> $GITHUB_OUTPUT + shell: bash + - uses: aica-technology/.github/.github/actions/compare-versions@v0.11.0 + id: check + with: + previous_version: ${{ steps.versions.outputs.prev_version }} + new_version: ${{ steps.versions.outputs.new_version }} + + metadata: + name: Get metadata + needs: check-version + runs-on: ubuntu-latest + outputs: + image_name: ${{ steps.ensure-image.outputs.image_name }} + image_tags: ${{ steps.tags.outputs.image_tags }} + create_tag: ${{ steps.tags.outputs.create_tag }} + git_tag: ${{ steps.tags.outputs.git_tag }} + steps: + - uses: aica-technology/.github/.github/actions/ghcr-ensure-prefix@v0.6.0 + id: ensure-image + with: + image_name: aica-technology/control-libraries + + - run: | + CREATE_TAG=false + GIT_TAG="" + if [ ${{ needs.check-version.outputs.has_changed }} = 'true' ]; then + CREATE_TAG=true + GIT_TAG="v${{ needs.check-version.outputs.version }}" + IMAGE_TAGS=latest,"${GIT_TAG}",rolling + else + IMAGE_TAGS=rolling + fi + echo "Image tags: ${IMAGE_TAGS}" + echo "Create tag: ${CREATE_TAG}" + echo "Git tag: ${GIT_TAG}" + echo "image_tags=${IMAGE_TAGS}" >> $GITHUB_OUTPUT + echo "create_tag=${CREATE_TAG}" >> $GITHUB_OUTPUT + echo "git_tag=${GIT_TAG}" >> $GITHUB_OUTPUT + id: tags + shell: bash + + build: + needs: [check-version, metadata] + strategy: + matrix: + arch: [amd64, arm64] + include: + - image: ubuntu-latest + # FIXME: using 4vcpu image because of heavy RAM usage when building pinoccio on arm64 + - image: buildjet-4vcpu-ubuntu-2204-arm + arch: arm64 + + runs-on: ${{ matrix.image }} + name: Build and publish (${{ matrix.arch }}) + steps: + - uses: actions/checkout@v3 + + - uses: aica-technology/.github/.github/actions/list-add-suffixes@v0.6.1 + id: merge-tags + with: + list: ${{ needs.metadata.outputs.image_tags }} + suffixes: ${{ matrix.arch }} + glue_separator: "-" + + - uses: aica-technology/.github/.github/actions/ghcr-build@v0.6.1 + with: + image_name: ${{ needs.metadata.outputs.image_name }} + image_tags: ${{ steps.merge-tags.outputs.list }} + build_flags: --build-arg VERSION=${{ needs.check-version.outputs.version }} + dockerfile_path: Dockerfile + token: ${{ secrets.GITHUB_TOKEN }} + + multi-arch: + runs-on: ubuntu-latest + name: Merge into a multi-arch image + needs: [metadata, build] + steps: + - uses: aica-technology/.github/.github/actions/ghcr-manifest-merge@v0.6.1 + with: + image_name: ${{ needs.metadata.outputs.image_name }} + image_tags: ${{ needs.metadata.outputs.image_tags }} + archs: amd64,arm64 + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 127479460..80fbffb72 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -1,46 +1,73 @@ name: Build and Test -# Run workflow on pushes to main and develop branches, on any pull request, or by manual dispatch on: push: branches: - main - - develop pull_request: workflow_dispatch: -# Define the build test jobs for each configuration jobs: - check-contribution: - name: Check if changelog and version have been updated + check-changelog: + name: Check if changelog has been updated runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - - name: Check contributions + - name: Check changelog if: ${{ github.event.pull_request.base.sha }} run: | - git config user.name github-actions[bot] - git config user.email github-actions[bot]@users.noreply.github.com - git fetch origin main ${{ github.event.pull_request.base.sha }} ${{ github.head_ref }} - git checkout ${{ github.head_ref }} - VER_DIFF=$(git diff ${{ github.event.pull_request.base.sha }} ${{ github.sha }} -- ./VERSION) - if ! [ "${VER_DIFF}" ]; then - bash update_version.sh --commit && git push - fi - CL_DIFF=$(git diff ${{ github.event.pull_request.base.sha }} ${{ github.sha }} -- ./CHANGELOG.md) + git fetch origin main ${{ github.event.pull_request.base.sha }} + CL_DIFF=$(git diff ${{ github.event.pull_request.base.sha }} ${{ github.sha }} -- CHANGELOG.md) if ! [ "${CL_DIFF}" ]; then - SEARCH_STRING="## Upcoming changes (in development)" - NEW_TITLE="${{ github.event.pull_request.title }} (#${{ github.event.pull_request.number }})" - sed -z "s/${SEARCH_STRING}\n/${SEARCH_STRING}\n\n- ${NEW_TITLE}/" -i CHANGELOG.md - git add CHANGELOG.md && git commit -m "Update CHANGELOG" && git push + echo "::error file="CHANGELOG.md",title=Check failed::CHANGELOG.md must be updated!" + exit 1 + fi + shell: bash + + check-version: + name: Check if version has been updated + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Check version + if: ${{ github.event.pull_request.base.sha }} + run: | + VERSION=$(echo $(> $GITHUB_OUTPUT + echo "new_version=${NEW_VERSION}" >> $GITHUB_OUTPUT + shell: bash + - uses: aica-technology/.github/.github/actions/compare-versions@v0.11.0 + id: check + with: + previous_version: ${{ steps.versions.outputs.prev_version }} + new_version: ${{ steps.versions.outputs.new_version }} + deploy: + needs: check-version name: Generate and Deploy runs-on: ubuntu-latest steps: - - uses: actions/checkout@master + - uses: actions/checkout@v4 - name: Generate docs - uses: mattnotmitt/doxygen-action@v1 + uses: mattnotmitt/doxygen-action@v1.9 with: working-directory: 'doxygen' doxyfile-path: 'doxygen.conf' - - name: Tag release version - if: ${{ github.event_name == 'release' }} - shell: bash - run: | - TAG="${GITHUB_REF#refs/tags/}" - TAG="${TAG/\//-}" - mkdir -p doxygen/docs/versions - sudo mv doxygen/docs/html doxygen/docs/versions/${TAG} - - - name: Tag branch version - if: ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' }} + - name: Tag version shell: bash run: | - BRANCH="${GITHUB_REF#refs/heads/}" - BRANCH="${BRANCH/\//-}" mkdir -p doxygen/docs/versions - sudo mv doxygen/docs/html doxygen/docs/versions/${BRANCH} + sudo mv doxygen/docs/html doxygen/docs/versions/rolling + if [ ${{ needs.check-version.outputs.has_changed }} = 'true' ]; then + sudo cp -r doxygen/docs/versions/rolling doxygen/docs/versions/latest + sudo cp -r doxygen/docs/versions/rolling doxygen/docs/versions/${{ needs.check-version.outputs.version }} + fi - name: Deploy to documentation branch uses: peaceiris/actions-gh-pages@v3 diff --git a/CHANGELOG.md b/CHANGELOG.md index 52b1e281c..61cf44874 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ Release Versions +- [8.0.0](#800) - [7.4.0](#740) - [7.3.0](#730) - [7.2.0](#720) @@ -12,6 +13,51 @@ Release Versions - [6.3.0](#630) - [6.2.0](#620) +## 8.0.0 + +Version 8.0.0 is a major update that adds new state types and collision detection features to control-libraries. + +### Breaking changes + +**robot_model** + +As part of the collision detection features in `robot_model::Model`, the dependencies of the `robot_model` module have +changed which constitutes a breaking change that requires users of the module to rebuild their code. + +**General** + +As of version 8.0.0, the `develop` branch will be deleted and the Linear Git-Flow workflow will be abandoned in favor of +easier release cycles (see [CONTRIBUING](./CONTRIBUTING.md)). Additionally, the `development-dependencies` and +`proto-dependencies` images will no longer be supported or maintained. + +### Features + +The `state_representation` module was extended with two new classes, `AnalogIOState` and `DigitalIOState`. Additionally, +the `robot_model` module now supports collision detection features from pinocchio, allowing to retrieve minimum +distances between links. + +### General + +The behind-the-scenes structural improvements to the build system and the CI that have existed in parallel since version +7.1.0 have now replaced the legacy build system with multiple shell scripts and Dockerfiles. All information regarding +building and using control-libraries should still be available in the READMEs. + +### Full changelog + +- feat: add metadata to docker image (#188) +- chore: touch up workflows and documentation (#181) +- feat: update demos directory (#179) +- fix: update copy constructor to avoid warnings (#180) +- build: remove deprecated Dockerfiles and scripts and update installation instructions (#176) +- refactor: optimize copy and swap constructor for robot model (#174) +- fix: refactor cmake project to deal with robot model dependencies (#178) +- feat: integrate minimum distance calculation feature into robot model(#167) +- ci: update workflows (#175) +- feat: integrate collision detection feature into robot model (#163) +- ci: use caching from docker to run tests in CI (#169) +- build: add missing licenses (#170) +- feat(build): handle installation and linking of dependencies for pinocchio collision support (#161) + ## 7.4.0 Version 7.4.0 brings Analog and Digital IO State types as a new feature to the `state_representation` module. diff --git a/CMakeLists.txt b/CMakeLists.txt index e9ba45fae..4b065887f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,12 @@ cmake_minimum_required(VERSION 3.15) project(all_control_libraries) +option(BUILD_PROTOCOL "Build and install the protocol" ON) + add_subdirectory(source) -add_subdirectory(protocol/clproto_cpp) +if(BUILD_PROTOCOL) + add_subdirectory(protocol/clproto_cpp) +endif() if(BUILD_TESTING) # reexport the test target defined in the subdirectories @@ -12,5 +16,5 @@ endif() # add licenses install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/licenses" - DESTINATION "share/doc/control-libraries/licenses" + DESTINATION "share/doc/control-libraries" ) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 154dce690..cbc33a1f0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,16 +1,13 @@ # Contributing -This repository is owned and maintained by AICA SA. We welcome user engagement to find bugs, resolve issues -and suggest useful features. +This repository is owned and maintained by [AICA SA](https://www.aica.tech/). We welcome user engagement to find bugs, +resolve issues and suggest useful features. -Before contributing to this repository, please first discuss the change you wish to make by using the repository -[Discussions](https://github.com/aica-technology/control-libraries/discussions) or opening an +Before contributing to this repository, please first discuss the change you wish to make by opening an [issue](https://github.com/aica-technology/control-libraries/issues). When you are ready to contribute, -[fork the repository and open a Pull Request (PR) from your feature branch](https://docs.github.com/en/get-started/quickstart/contributing-to-projects), -making sure to **target the `develop` branch of the `aica-technology/control-libraries` repository**. -Refer to the [PR process](#pull-request-process) section for more information. +[fork the repository and open a Pull Request (PR) from your feature branch](https://docs.github.com/en/get-started/quickstart/contributing-to-projects). Refer to the [PR process](#pull-request-process) section for more information. Before the PR can be accepted, contributors who are not employed by AICA must first read and agree to the [Contributor License Agreement (CLA)](./licenses/CLA.md), which grants AICA the rights to use, modify and distribute @@ -18,39 +15,9 @@ open source contributions. ## Development Environment -Our development and testing workflow uses a Docker container to host the project build dependencies which an IDE then -accesses remotely via SSH. - -The following section describes the configuration steps to use this workflow. Of course, contributors may use whatever -development environment they prefer, as long as they adhere to the overall contribution guidelines. - -### Configuring the development environment - -Prerequisites: Install [Docker](https://docs.docker.com/get-docker/) -and [CLion IDE](https://www.jetbrains.com/clion/download). - -Step 1: Build and run the development container server with `./dev-server.sh`. The script requires access to your public -RSA key file. You may additionally specify a custom port. Run `./dev-server.sh --help` for more details. - -Step 2: If not already done, -[create a remote toolchain in CLion](https://www.jetbrains.com/help/clion/remote-projects-support.html#remote-toolchain) -using the following credentials: - -- Host: `127.0.0.1` -- Port: `2222` (or custom specified port) -- User name: `developer` -- Authentication type: `Key pair` - -Step 3: If not already done, -[create a CMake profile that uses the remote toolchain](https://www.jetbrains.com/help/clion/remote-projects-support.html#CMakeProfile). - -Step 4: [Resync the header search paths](https://www.jetbrains.com/help/clion/remote-projects-support.html#resync). -Repeat this step any time you change the compiler or project dependencies. Optionally you can enable automatic -synchronization. - -Step 5: -[Select the remote CMake profile](https://www.jetbrains.com/help/clion/remote-projects-support.html#WorkWithRemote) -to build, run and debug library and test targets entirely with the remote toolchain. +We provide a [VS Code Dev Containter configuration file](./.devcontainer/devcontainer.json) for development and testing +in a Docker container. Simply install VS Code and its Dev Container extension and then choose the +`Dev Containers: Open Folder in Container ...` option from the command palette. ## Style guide @@ -69,8 +36,9 @@ guide to the testing framework. If you are using a properly integrated development environment, you can run and debug the tests for each module locally to check the behaviour. -You may also use the script `./build-test.sh` to build the project libraries and run all tests within a Docker -container. Because this process rebuilds the project from scratch, each evaluation may take several minutes. +You may also build the `python-test` stage of the main [Dockerfile](./Dockerfile) to build the project libraries and run +all tests within a Docker container. Because this process rebuilds the project from scratch, each evaluation may take +several minutes. ## Pull Request Process @@ -79,33 +47,27 @@ container. Because this process rebuilds the project from scratch, each evaluati 3. Document the header files and public functions with doxygen comments, and update any relevant README.md or documentation files with details of changes to the interface. 4. Update the [changelog](CHANGELOG.md) with your feature / fix / improvement in the "Upcoming changes" section. -5. Update the version number using the [update_version.sh](./update_version.sh) script. -6. Open a pull request into the `develop` branch. Write a meaningful title and description for the PR to make it +6. Open a pull request into the `main` branch. Write a meaningful title and description for the PR to make it clear what changes you have made, why you have made them, and how you have tested the changes. -7. You may merge the pull request into `develop` once you have the sign-off of one other developer and all CI tests +7. You may merge the pull request into `main` once you have the sign-off of one other developer and all CI tests pass. Always use the "Squash and Merge" option to ensure your changes are contained within a single commit, maintaining a linear git history. If unsure, you may request another reviewer to merge it for you. ## Release strategy -The `main` branch is updated from `develop` at regular release intervals using traditional semantic versioning -(major.minor.patch). +All pull requests are merged into `main` using the "Squash and Merge" option. To trigger new releases, the version of +the project version is increased using traditional semantic versioning (major.minor.patch) at regular intervals. The major release number should be incremented whenever there is a breaking change to the public API (for example, when a previously existing function is deleted or renamed). Minor version numbers contain general new features and improvements, while patch numbers represent simple and small fixes. -The `develop` branch is always considered to be a "release candidate" that contains only release-ready code. If, at -release time, there are features on `develop` that are considered unfinished or broken, they can be marked +The `main` branch is always considered to be a "release candidate" that contains only release-ready code. If, at +release time, there are features on `main` that are considered unfinished or broken, they can be marked as `EXPERIMENTAL` to exclude them from compilation. -At the time of release, usually when there is minor or major version update, a release branch should be made from -development. - -The release branch should be used to finalize the [changelog](CHANGELOG.md), which includes moving all content from +At the time of release, usually when there is minor or major version update, a release branch should be made. The +release branch should be used to finalize the [changelog](CHANGELOG.md), which includes moving all content from the "Upcoming changes (in development)" header under a new header with the corresponding release version. -Once the changes specific to the release have been approved, a linear GitFlow strategy is used to merge this release -branch into `main`, and then additionally squash and rebase the release branch back into `develop`. - The release on `main` should be tagged with the corresponding version as `vX.Y.Z`. diff --git a/Dockerfile b/Dockerfile index 566edfc87..fbc09a471 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,6 @@ RUN apt-get update && apt-get install -y \ g++ \ git \ libgtest-dev \ - libeigen3-dev \ python3-pip \ ssh \ sudo \ @@ -19,6 +18,8 @@ RUN echo "Set disable_coredump false" >> /etc/sudo.conf # create the credentials to be able to pull private repos using ssh RUN mkdir /root/.ssh/ && ssh-keyscan github.com | tee -a /root/.ssh/known_hosts +ARG CMAKE_BUILD_TYPE=Release + FROM base as apt-dependencies COPY apt-packages.tx[t] / @@ -76,49 +77,65 @@ xargs -a /tmp/new-packages.txt dpkg-query -L \ # this root can then be copied to / to install everything globally or use LD_LIBRARY_PATH to use it locally HEREDOC -FROM base as dep-pinocchio +FROM base as base-dependencies +ARG TARGETPLATFORM +ARG CACHEID +COPY dependencies/base_dependencies.cmake CMakeLists.txt +RUN --mount=type=cache,target=/build,id=cmake-base-deps-${TARGETPLATFORM}-${CACHEID},uid=1000 \ + cmake -B build -DBUILD_TESTING=OFF -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} && cmake --build build && cmake --install build --prefix /tmp/deps + +FROM base as pinocchio-dependencies COPY --from=apt-dependencies /tmp/apt / +COPY --from=base-dependencies /tmp/deps /usr ARG TARGETPLATFORM ARG CACHEID -ARG PINOCCHIO_TAG=v2.6.9 -ARG PINOCCHIO_TESTS=OFF +ARG PINOCCHIO_TAG=v2.6.20 +ARG HPP_FCL_TAG=v2.4.4 # FIXME: it would be nicer to have it all in the root CMakelists.txt but: # * `pinocchio` doesn't provide an include directory we can easily plug into `target_include_directories` and thus needs to be installed first # * `pinocchio` uses hacks relying on undocumented CMake quirks which break if you use `FetchContent` # FIXME: it needs `CMAKE_INSTALL_PREFIX` and `--prefix` because it doesn't install to the right place otherwise -RUN --mount=type=cache,target=./pinocchio,id=cmake-pinocchio-src-${PINOCCHIO_TAG}-${TARGETPLATFORM}-${CACHEID},uid=1000 \ - --mount=type=cache,target=./build,id=cmake-pinocchio-${PINOCCHIO_TAG}-${TARGETPLATFORM}-${CACHEID},uid=1000 \ - if [ ! -f pinocchio/CMakeLists.txt ]; then rm -rf pinocchio/* && git clone --depth 1 -b ${PINOCCHIO_TAG} --recursive https://github.com/stack-of-tasks/pinocchio; fi \ - && cmake -B build -S pinocchio -DBUILD_TESTING=${PINOCCHIO_TESTS} -DCMAKE_BUILD_TYPE=Release -DBUILD_PYTHON_INTERFACE=OFF -DCMAKE_INSTALL_PREFIX=/tmp/deps \ - && cmake --build build --target all install -# FIXME: pinocchio produces non-portable paths -RUN find /tmp/deps -type f -exec sed -i 's#/tmp/deps#/usr#g' '{}' \; +RUN --mount=type=cache,target=/pinocchio,id=cmake-pinocchio-src-${PINOCCHIO_TAG}-${TARGETPLATFORM}-${CACHEID},uid=1000 \ + --mount=type=cache,target=/hpp-fcl,id=cmake-hpp-fcl-src-${HPP_FCL_TAG}-${TARGETPLATFORM}-${CACHEID},uid=1000 \ + --mount=type=cache,target=/build,id=cmake-pinocchio-${PINOCCHIO_TAG}-${HPP_FCL_TAG}-${TARGETPLATFORM}-${CACHEID},uid=1000 \ +< /etc/ssh/sshd_config_development \ - && mkdir /run/sshd - -ENV USER developer -ENV HOME /home/${USER} - -# create and configure a new user -ARG UID=1000 -ARG GID=1000 -RUN addgroup --gid ${GID} ${USER} -RUN adduser --gecos "Remote User" --uid ${UID} --gid ${GID} ${USER} && yes | passwd ${USER} -RUN usermod -a -G dialout ${USER} -RUN echo "${USER} ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/99_aptget -RUN chmod 0440 /etc/sudoers.d/99_aptget && chown root:root /etc/sudoers.d/99_aptget - -# Configure sshd entrypoint to authorise the new user for ssh access and -# optionally update UID and GID when invoking the container with the entrypoint script -COPY ./docker/sshd_entrypoint.sh /sshd_entrypoint.sh -RUN chmod 744 /sshd_entrypoint.sh - -# create the credentials to be able to pull private repos using ssh -RUN mkdir /root/.ssh/ && ssh-keyscan github.com | tee -a /root/.ssh/known_hosts - -RUN echo "session required pam_limits.so" | tee --append /etc/pam.d/common-session > /dev/null - -WORKDIR ${HOME} diff --git a/Dockerfile.proto b/Dockerfile.proto deleted file mode 100644 index e468f892e..000000000 --- a/Dockerfile.proto +++ /dev/null @@ -1,34 +0,0 @@ -ARG BASE_TAG=22.04 -FROM ubuntu:${BASE_TAG} as build-stage -ENV DEBIAN_FRONTEND=noninteractive - -RUN apt-get update && apt-get install -y \ - autoconf \ - cmake \ - g++ \ - gcc \ - libtool \ - make \ - wget \ - && apt-get clean \ - && rm -rf /var/lib/apt/lists/* - -WORKDIR /tmp -ARG PROTOBUF_VERSION=21.0 -RUN wget -O protobuf-cpp-"${PROTOBUF_VERSION}".tar.gz \ - https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOBUF_VERSION}/protobuf-cpp-3.${PROTOBUF_VERSION}.tar.gz \ - && tar -xzf protobuf-cpp-"${PROTOBUF_VERSION}".tar.gz \ - && rm protobuf-cpp-"${PROTOBUF_VERSION}".tar.gz - -WORKDIR /tmp/protobuf-3."${PROTOBUF_VERSION}" -RUN ./autogen.sh \ - && ./configure \ - && make -j $(nproc --ignore=1) \ - && make install - - -FROM ubuntu:${BASE_TAG} as google-dependencies -COPY --from=build-stage /usr/local/include/google /usr/local/include/google -COPY --from=build-stage /usr/local/lib/libproto* /usr/local/lib/ -COPY --from=build-stage /usr/local/bin/protoc /usr/local/bin -RUN ldconfig diff --git a/README.md b/README.md index cda084a8c..06d61109d 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ - - build-push workflow badge - contribution license agreement workflow badge - page build and deployment workflow badge + build-release workflow badge + build-test workflow badge + contribution license agreement workflow badge + page build and deployment workflow badge # Control Libraries @@ -10,44 +10,12 @@ The `control-libraries` project is a collection of modules to facilitate the creation of control loop algorithms for robotics, including trajectory planning, kinematics, dynamics and control. -Code documentation is available at -aica-technology.github.io/control-libraries. - -## Releases - -The latest stable version of the project is available on the -[`main`](https://github.com/aica-technology/control-libraries/tree/main), while the latest pre-release development -build is available on the [`develop`](https://github.com/aica-technology/control-libraries/tree/develop) branch. - -Refer to the [Releases](https://github.com/aica-technology/control-libraries/releases) page for other versions. - - - - - - - - - - - - - - - -
BranchStatus
- - main - - - main branch build-test workflow badge -
- - develop - - - develop branch build-test workflow badge -
+Code documentation is available at +[aica-technology.github.io/control-libraries](https://aica-technology.github.io/control-libraries). + +The rolling version of the project is available on the +[`main`](https://github.com/aica-technology/control-libraries/tree/main) branch. Refer to the +[Releases](https://github.com/aica-technology/control-libraries/releases) page for other versions. ## Core libraries @@ -60,32 +28,115 @@ The core libraries are implemented in C++ and comprise the following modules: Source code, documentation and installation instructions are available under the [source](./source) folder. +## Protocol + +There is a module that defines the protocol for sending and receiving messages containing control libraries data across +any network, based on the Google Protocol Buffer. For its implementation, installation and documentation, see the +[protocol](./protocol) folder. + ## Python bindings There exist Python bindings for the control library modules and the protocol module. See the [python](./python) folder for installation instructions. -## Protocol - -There is a module that defines the protocol for sending and receiving messages containing control libraries -data across any network, based on the Google Protocol Buffer. For its implementation, installation and -documentation, see the [protocol](./protocol) folder. - ## Demos For examples and demos in C++ and Python, refer to the [demos](./demos) folder. ## Contributing -We welcome user engagement to find bugs, resolve issues and suggest useful features. -Refer to the [contribution guidelines](./CONTRIBUTING.md) for more information. +We welcome user engagement to find bugs, resolve issues and suggest useful features. Refer to the +[contribution guidelines](./CONTRIBUTING.md) for more information. ## License -This project is provided free and open-source under the GPLv3 license. -See the [licenses](./licenses) folder for more information. +This project is provided free and open-source under the GPLv3 license. See the [licenses](./licenses) folder for more +information. + +## Installation + +### Supported platforms + +These libraries have been developed and tested on Linux Ubuntu 20.04 and 22.04. They should also work on macOS and +Windows, though the installation steps may differ. At this time no guarantees are made for library support on non-Linux +systems. + +### Installation with the install script + +This project uses CMake to generate static library objects for each of the modules. To facilitate the installation +process, an [install script](./install.sh) is provided. + +The install script takes care of all the installation steps, including the installation and configuration of all +dependencies. It can be run with several optional arguments: +- `-y`, `--auto`: Any input prompts will be suppressed and install steps automatically approved. +- `-d [path]`, `--dir [path]`: If provided, the installation directory will be changed to `[path]`. +- `--clean`: Any previously installed header files from `/usr/local/include` and any shared library files from + `/usr/local/lib` will be deleted before the installation. +- `--cleandir [path]`: Any previously installed header files shared library files from `[path]` will be deleted before + the installation. + +### Advanced options + +Users who prefer to perform the installation manually and/or have already installed some dependencies can selectively +do the steps from the install script. + +The CMake configuration flags for control libraries `BUILD_CONTROLLERS`, `BUILD_DYNAMICAL_SYSTEMS` and +`BUILD_ROBOT_MODEL` determine which modules are built, and are all defined as `ON` by default. The building of the +`state_representation` library cannot be disabled, as all other libraries depend on it. To selectively disable the build +of a particular module, set the flag to `=OFF`. For example, the following flags will prevent the `robot_model` module +from being built, which is useful if the Pinocchio dependency is not fulfilled on your system. + +```shell script +-DBUILD_ROBOT_MODEL=OFF +``` + +Similarly, if one is not interested in the installation of the [protocol](./protocol/README.md), it can be disabled with + +```shell script +-DBUILD_PROTOCOL_=OFF +``` + +The C++ `clproto` library requires control libraries [`state_representation`](../source/state_representation/README.md) +and [Google Protobuf](https://github.com/protocolbuffers/protobuf/blob/master/src/README.md) +to be installed on your computer, which includes the compiler `protoc` and the runtime library `libprotobuf.so`. + +To also build the tests, add the CMake flag `-DBUILD_TESTING=ON`. This requires GTest to be installed on your system. +You can then use `make test` to run all test targets. + +Alternatively, you can include the source code for each library as submodules in your own CMake project, using the CMake +directive `add_subdirectory(...)` to link it with your project. + +### Installation of Python bindings + +You must first install the C++ modules before you can install the Python bindings. Additionally, the installation of the +bindings requires the following prerequisites: +- `python3` >= 3.0 +- `pip3` >= 10.0.0 + +The installation itself is then quite straightforward: +```shell +python3 pip install ./python +``` + +If the installation fails, it may be because of non-default installation directories for some dependencies. In this +case, the include path for OSQP can be set through environment variables before the pip install. + +```shell +export OSQP_INCLUDE_DIR='/path/to/include/osqp' # replace /path/to/include with installation directory +python3 pip install ./python +``` + +The example above installs the module to the default dist-packages location. You can see more information about the +installed module using `pip3 show control-libraries`. + +The process also works with Python virtual environments. For example, with `pipenv`: + +```shell script +## pip3 install pipenv + +pipenv install ./python +``` ## External resources -- [Docker images with control libraries installations](https://github.com/aica-technology/docker-images) - [Modulo: an extension layer to ROS2 based on control libraries](https://github.com/aica-technology/modulo) diff --git a/VERSION b/VERSION index ba7f754d0..ae9a76b92 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -7.4.0 +8.0.0 diff --git a/apt-packages.txt b/apt-packages.txt index 284f4ad48..2988803ab 100644 --- a/apt-packages.txt +++ b/apt-packages.txt @@ -1,2 +1,4 @@ libboost-all-dev +libeigen3-dev liburdfdom-dev +libassimp-dev diff --git a/demos/CMakeLists.txt b/demos/CMakeLists.txt index 881cc7b8c..ddb9d359e 100644 --- a/demos/CMakeLists.txt +++ b/demos/CMakeLists.txt @@ -15,7 +15,7 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-Wall -Wextra -Wpedantic) endif() -find_package(control_libraries 7.4.0 CONFIG REQUIRED) +find_package(control_libraries 8.0.0 CONFIG REQUIRED) set(DEMOS_SCRIPTS task_space_control_loop diff --git a/demos/Dockerfile b/demos/Dockerfile index 6902e9974..89d35cd45 100644 --- a/demos/Dockerfile +++ b/demos/Dockerfile @@ -1,20 +1,17 @@ -ARG BASE_TAG=latest -FROM ghcr.io/aica-technology/control-libraries/development-dependencies:${BASE_TAG} as build -ARG BRANCH=develop +FROM ghcr.io/aica-technology/control-libraries:rolling as cl +FROM ubuntu:22.04 +ENV DEBIAN_FRONTEND=noninteractive -WORKDIR /source -RUN git clone --depth 1 --branch ${BRANCH} https://github.com/aica-technology/control-libraries -RUN bash control-libraries/source/install.sh --auto -RUN bash control-libraries/protocol/install.sh --auto -RUN pip3 install control-libraries/python +RUN apt-get update && apt-get install -y \ + cmake \ + g++ \ + python3 \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* -RUN rm -rf /source +COPY --from=cl / / - -FROM build as demos - -USER developer -WORKDIR ${HOME}/control_loop_examples +WORKDIR /control_loop_examples COPY ./ ./ -RUN mkdir build && cd build && cmake .. && sudo make -j all && sudo make install +RUN mkdir build && cd build && cmake .. && make -j all && make install diff --git a/demos/README.md b/demos/README.md index 96cc96dd4..e9b79b247 100644 --- a/demos/README.md +++ b/demos/README.md @@ -19,9 +19,9 @@ demo scripts and run the one of your choice: ```console ./run-demo-script.sh # Run a python script -developer@xxxxxxxxx:~/control_loop_examples$ python3 python_scripts/