├── simple-listener-dl-py ├── src │ └── app │ │ ├── resource │ │ └── app │ │ ├── app │ │ ├── __init__.py │ │ └── main.py │ │ ├── ros2 │ │ ├── __init__.py │ │ └── ros2_listener_ctrlx_provider.py │ │ ├── setup.cfg │ │ ├── ctrlx_datalayer │ │ ├── __init__.py │ │ ├── ctrlx_provider_node.py │ │ └── ctrlx_datalayer_helper.py │ │ ├── package.xml │ │ └── setup.py ├── build-snap-amd64.sh ├── .vscode │ └── settings.json ├── .gitignore ├── wrapper │ └── run.sh ├── snap │ └── snapcraft.yaml └── README.md ├── simple-talker-dl-py ├── src │ └── app │ │ ├── resource │ │ └── app │ │ ├── app │ │ ├── __init__.py │ │ └── main.py │ │ ├── setup.cfg │ │ ├── ros2 │ │ ├── __init__.py │ │ └── datalayer_reader_ros2_publisher.py │ │ ├── ctrlx_datalayer │ │ ├── __init__.py │ │ └── ctrlx_datalayer_helper.py │ │ ├── package.xml │ │ └── setup.py ├── build-snap-amd64.sh ├── .vscode │ └── settings.json ├── .gitignore ├── wrapper │ └── run.sh ├── snap │ └── snapcraft.yaml └── README.md ├── simple-talker-py ├── src │ └── talker │ │ ├── resource │ │ └── talker │ │ ├── talker │ │ ├── __init__.py │ │ └── main_minimal_publisher.py │ │ ├── setup.cfg │ │ ├── package.xml │ │ └── setup.py ├── build-snap-amd64.sh ├── .gitignore ├── wrapper │ └── run.sh ├── snap │ └── snapcraft.yaml └── README.md ├── simple-listener-py ├── src │ └── listener │ │ ├── resource │ │ └── listener │ │ ├── listener │ │ ├── __init__.py │ │ └── main_minimal_subscriber.py │ │ ├── setup.cfg │ │ ├── package.xml │ │ └── setup.py ├── build-snap-amd64.sh ├── .gitignore ├── .vscode │ ├── settings.json │ └── launch.json ├── wrapper │ └── run.sh ├── snap │ └── snapcraft.yaml └── README.md ├── simple-listener-cpp ├── build-snap-amd64.sh ├── .vscode │ └── settings.json ├── .gitignore ├── src │ └── app │ │ ├── package.xml │ │ ├── CMakeLists.txt │ │ └── src │ │ └── subscriber_member_function.cpp ├── wrapper │ └── run-listener.sh ├── snap │ └── snapcraft.yaml └── README.md ├── simple-talker-cpp ├── build-snap-amd64.sh ├── .gitignore ├── src │ └── app │ │ ├── package.xml │ │ ├── CMakeLists.txt │ │ └── src │ │ └── publisher_member_function.cpp ├── wrapper │ └── run-talker.sh ├── snap │ └── snapcraft.yaml └── README.md ├── simple-talker-dl-cpp ├── build-snap-amd64.sh ├── .gitignore ├── .vscode │ ├── settings.json │ └── tasks.json ├── src │ └── app │ │ ├── package.xml │ │ ├── CMakeLists.txt │ │ └── src │ │ └── subscriber_member_function.cpp ├── wrapper │ └── run-listener.sh ├── snap │ └── snapcraft.yaml └── README.md ├── simple-listener-dl-cpp ├── build-snap-amd64.sh ├── .gitignore ├── .vscode │ ├── settings.json │ └── tasks.json ├── src │ └── app │ │ ├── package.xml │ │ ├── CMakeLists.txt │ │ └── src │ │ ├── ctrlx_datalayer_helper.h │ │ └── subscriber_member_function.cpp ├── wrapper │ └── run-listener.sh ├── snap │ └── snapcraft.yaml └── README.md ├── ros2-base-humble-deb ├── .gitignore ├── build-snap-amd64.sh ├── snap │ └── snapcraft.yaml └── README.md ├── LICENSES ├── LICENSE-images ├── MIT.txt └── Apache-2.0.txt ├── SECURITY.md ├── scripts ├── prepare-build-snap.sh ├── colcon-build.sh ├── build-snap-py.sh ├── install-ctrlx-datalayer-deb.sh ├── build-snap-cpp.sh ├── setup-ctrlx-datalayer-deb.sh ├── README.md ├── install-snapcraft.sh └── setup-system-humble-jammy.sh ├── CONTRIBUTORS.md ├── CONTRIBUTING.md ├── .editorconfig ├── LICENSE ├── .github └── workflows │ └── main.yml ├── CODE_OF_CONDUCT.md ├── README.md └── .gitignore /simple-listener-dl-py/src/app/resource/app: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /simple-talker-dl-py/src/app/resource/app: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /simple-talker-py/src/talker/resource/talker: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /simple-listener-py/src/listener/resource/listener: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /simple-talker-py/build-snap-amd64.sh: -------------------------------------------------------------------------------- 1 | ../scripts/build-snap-py.sh -------------------------------------------------------------------------------- /simple-listener-cpp/build-snap-amd64.sh: -------------------------------------------------------------------------------- 1 | ../scripts/build-snap-cpp.sh -------------------------------------------------------------------------------- /simple-listener-dl-py/build-snap-amd64.sh: -------------------------------------------------------------------------------- 1 | ../scripts/build-snap-py.sh -------------------------------------------------------------------------------- /simple-listener-py/build-snap-amd64.sh: -------------------------------------------------------------------------------- 1 | ../scripts/build-snap-py.sh -------------------------------------------------------------------------------- /simple-talker-cpp/build-snap-amd64.sh: -------------------------------------------------------------------------------- 1 | ../scripts/build-snap-cpp.sh -------------------------------------------------------------------------------- /simple-talker-dl-cpp/build-snap-amd64.sh: -------------------------------------------------------------------------------- 1 | ../scripts/build-snap-cpp.sh -------------------------------------------------------------------------------- /simple-talker-dl-py/build-snap-amd64.sh: -------------------------------------------------------------------------------- 1 | ../scripts/build-snap-py.sh -------------------------------------------------------------------------------- /simple-listener-dl-cpp/build-snap-amd64.sh: -------------------------------------------------------------------------------- 1 | ../scripts/build-snap-cpp.sh -------------------------------------------------------------------------------- /simple-listener-cpp/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ros.distro": "humble" 3 | } -------------------------------------------------------------------------------- /simple-listener-dl-py/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ros.distro": "humble" 3 | } -------------------------------------------------------------------------------- /simple-talker-dl-py/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ros.distro": "humble" 3 | } -------------------------------------------------------------------------------- /simple-talker-dl-py/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | install/ 3 | log/ 4 | __pycache__/ 5 | prime/ 6 | parts/ 7 | stage/ -------------------------------------------------------------------------------- /simple-talker-py/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | install/ 3 | log/ 4 | __pycache__/ 5 | prime/ 6 | parts/ 7 | stage/ -------------------------------------------------------------------------------- /ros2-base-humble-deb/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | install/ 3 | log/ 4 | __pycache__/ 5 | prime/ 6 | parts/ 7 | stage/ -------------------------------------------------------------------------------- /simple-listener-dl-py/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | install/ 3 | log/ 4 | __pycache__/ 5 | prime/ 6 | parts/ 7 | stage/ -------------------------------------------------------------------------------- /simple-listener-cpp/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | install/ 3 | log/ 4 | __pycache__/ 5 | prime/ 6 | parts/ 7 | stage/ 8 | squashfs-root/ -------------------------------------------------------------------------------- /simple-listener-py/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | install/ 3 | log/ 4 | __pycache__/ 5 | prime/ 6 | parts/ 7 | stage/ 8 | squashfs-root/ -------------------------------------------------------------------------------- /simple-talker-dl-cpp/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | install/ 3 | log/ 4 | __pycache__/ 5 | prime/ 6 | parts/ 7 | stage/ 8 | squashfs-root/ -------------------------------------------------------------------------------- /simple-talker-dl-py/src/app/app/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Bosch Rexroth AG 2 | # 3 | # SPDX-License-Identifier: MIT -------------------------------------------------------------------------------- /simple-talker-dl-py/src/app/setup.cfg: -------------------------------------------------------------------------------- 1 | [develop] 2 | script_dir=$base/lib/app 3 | [install] 4 | install_scripts=$base/lib/app 5 | -------------------------------------------------------------------------------- /simple-listener-dl-cpp/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | install/ 3 | log/ 4 | __pycache__/ 5 | prime/ 6 | parts/ 7 | stage/ 8 | squashfs-root/ -------------------------------------------------------------------------------- /simple-listener-dl-py/src/app/app/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Bosch Rexroth AG 2 | # 3 | # SPDX-License-Identifier: MIT -------------------------------------------------------------------------------- /simple-listener-dl-py/src/app/ros2/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Bosch Rexroth AG 2 | # 3 | # SPDX-License-Identifier: MIT -------------------------------------------------------------------------------- /simple-listener-dl-py/src/app/setup.cfg: -------------------------------------------------------------------------------- 1 | [develop] 2 | script_dir=$base/lib/app 3 | [install] 4 | install_scripts=$base/lib/app 5 | -------------------------------------------------------------------------------- /simple-talker-dl-py/src/app/ros2/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Bosch Rexroth AG 2 | # 3 | # SPDX-License-Identifier: MIT -------------------------------------------------------------------------------- /simple-talker-py/src/talker/talker/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Bosch Rexroth AG 2 | # 3 | # SPDX-License-Identifier: MIT -------------------------------------------------------------------------------- /simple-listener-py/src/listener/listener/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Bosch Rexroth AG 2 | # 3 | # SPDX-License-Identifier: MIT -------------------------------------------------------------------------------- /simple-talker-py/src/talker/setup.cfg: -------------------------------------------------------------------------------- 1 | [develop] 2 | script_dir=$base/lib/talker 3 | [install] 4 | install_scripts=$base/lib/talker 5 | -------------------------------------------------------------------------------- /simple-listener-dl-py/src/app/ctrlx_datalayer/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Bosch Rexroth AG 2 | # 3 | # SPDX-License-Identifier: MIT -------------------------------------------------------------------------------- /simple-listener-py/src/listener/setup.cfg: -------------------------------------------------------------------------------- 1 | [develop] 2 | script_dir=$base/lib/listener 3 | [install] 4 | install_scripts=$base/lib/listener 5 | -------------------------------------------------------------------------------- /simple-talker-dl-py/src/app/ctrlx_datalayer/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Bosch Rexroth AG 2 | # 3 | # SPDX-License-Identifier: MIT -------------------------------------------------------------------------------- /ros2-base-humble-deb/build-snap-amd64.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | sudo snapcraft clean 5 | sudo snapcraft --build-for=amd64 --verbosity=verbose -------------------------------------------------------------------------------- /simple-talker-cpp/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | install/ 3 | log/ 4 | __pycache__/ 5 | prime/ 6 | parts/ 7 | stage/ 8 | squashfs-root/ 9 | .vscode/settings.json -------------------------------------------------------------------------------- /simple-talker-dl-cpp/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ros.distro": "humble", 3 | "files.associations": { 4 | "iostream": "cpp" 5 | } 6 | } -------------------------------------------------------------------------------- /LICENSES/LICENSE-images: -------------------------------------------------------------------------------- 1 | This license applies only to the images, fonts and assets in this repository. 2 | 3 | All rights reserved. 4 | 5 | Copyright (c) Bosch Rexroth AG 6 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | You can find all information on how to report vulnerabilities at https://psirt.bosch.com/report-a-vulnerability/. 2 | Please include the repository URL in your report. 3 | -------------------------------------------------------------------------------- /simple-listener-dl-cpp/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ros.distro": "humble", 3 | "files.associations": { 4 | "functional": "cpp", 5 | "new": "cpp" 6 | } 7 | } -------------------------------------------------------------------------------- /simple-listener-py/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "[python]": { 3 | "editor.defaultFormatter": "ms-python.autopep8" 4 | }, 5 | "python.formatting.provider": "none" 6 | } -------------------------------------------------------------------------------- /scripts/prepare-build-snap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export GNUTLS_CPUID_OVERRIDE=0x1 4 | export DEBIAN_FRONTEND=noninteractive 5 | export SNAPCRAFT_BUILD_ENVIRONMENT=host 6 | export SNAPCRAFT_ENABLE_EXPERIMENTAL_TARGET_ARCH=1 7 | -------------------------------------------------------------------------------- /CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | The following is a list of contributors to this repository in alphabetical order: 2 | 3 | * [Johannes Albrecht](https://github.com/albrecht-j), "Repo Maintainer" 4 | * [Sebastian Krauskopf](https://github.com/krauskopf) 5 | -------------------------------------------------------------------------------- /scripts/colcon-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rosdep install -i --from-path src --rosdistro humble -y 4 | if [ $? -eq 0 ] 5 | then 6 | echo " " 7 | else 8 | exit 1 9 | fi 10 | 11 | source /opt/ros/humble/setup.bash 12 | colcon build -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | If you want to contribute please feel free to use the issues area or contact one of the team members marked within the CONTRIBUTORS.md. Contribution of source code is currently only possible for team members. 4 | -------------------------------------------------------------------------------- /scripts/build-snap-py.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | ROOT_DIR=$(git rev-parse --show-toplevel) 5 | 6 | source ${ROOT_DIR}/scripts/colcon-build.sh 7 | 8 | if [ $? -eq 0 ] 9 | then 10 | echo " " 11 | else 12 | exit 1 13 | fi 14 | 15 | source ${ROOT_DIR}/scripts/prepare-build-snap.sh 16 | 17 | sudo snapcraft clean 18 | sudo snapcraft --build-for=amd64 --verbosity=verbose --destructive-mode 19 | -------------------------------------------------------------------------------- /scripts/install-ctrlx-datalayer-deb.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #set -e 4 | SDK_RELEASE_VERSION=${1:-3.4.0} 5 | DATALAYER_DEB_FILE_VERSION=${2:-2.8.6} 6 | 7 | ROOT_DIR=$(git rev-parse --show-toplevel) 8 | 9 | rm -rf ${ROOT_DIR}/deb 10 | mkdir -p ${ROOT_DIR}/deb 11 | 12 | wget --quiet https://github.com/boschrexroth/ctrlx-automation-sdk/releases/download/${SDK_RELEASE_VERSION}/ctrlx-datalayer-${DATALAYER_DEB_FILE_VERSION}.deb -P ${ROOT_DIR}/deb 13 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | ; https://editorconfig.org/ 2 | 3 | root = true 4 | 5 | [*] 6 | insert_final_newline = true 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | indent_style = space 10 | indent_size = 2 11 | 12 | [{Makefile,go.mod,go.sum,*.go,.gitmodules}] 13 | indent_style = tab 14 | indent_size = 4 15 | 16 | [*.{md,txt}] 17 | indent_style = space 18 | indent_size = 4 19 | trim_trailing_whitespace = false 20 | 21 | eclint_indent_style = unset -------------------------------------------------------------------------------- /scripts/build-snap-cpp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | ROOT_DIR=$(git rev-parse --show-toplevel) 5 | 6 | rm -rf install/ 7 | mkdir -p install/app 8 | rm -rf build/ 9 | rm -rf log/ 10 | 11 | source ${ROOT_DIR}/scripts/colcon-build.sh 12 | 13 | if [ $? -eq 0 ] 14 | then 15 | echo " " 16 | else 17 | exit 1 18 | fi 19 | 20 | source ${ROOT_DIR}/scripts/prepare-build-snap.sh 21 | 22 | sudo snapcraft clean 23 | sudo snapcraft --build-for=amd64 --verbosity=verbose --destructive-mode 24 | -------------------------------------------------------------------------------- /simple-listener-py/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Python: Current File", 9 | "type": "python", 10 | "request": "launch", 11 | "program": "${file}", 12 | "console": "integratedTerminal", 13 | "justMyCode": false 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /simple-talker-cpp/src/app/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | app 5 | 2.2.0 6 | Simple ROS 2 publisher (talker) in cpp 7 | boschrexroth 8 | MIT License 9 | 10 | ament_cmake 11 | 12 | rclcpp 13 | std_msgs 14 | sensor_msgs 15 | 16 | ament_lint_auto 17 | ament_lint_common 18 | 19 | 20 | ament_cmake 21 | 22 | 23 | -------------------------------------------------------------------------------- /simple-listener-cpp/src/app/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | app 5 | 2.2.0 6 | Simple ROS 2 subscriber (listener) in cpp 7 | boschrexroth 8 | MIT License 9 | 10 | ament_cmake 11 | 12 | rclcpp 13 | std_msgs 14 | sensor_msgs 15 | 16 | ament_lint_auto 17 | ament_lint_common 18 | 19 | 20 | ament_cmake 21 | 22 | 23 | -------------------------------------------------------------------------------- /simple-talker-dl-cpp/src/app/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | app 5 | 2.2.0 6 | Simple ROS 2 subscriber (listener) in cpp 7 | boschrexroth 8 | MIT License 9 | 10 | ament_cmake 11 | 12 | rclcpp 13 | std_msgs 14 | sensor_msgs 15 | 16 | ament_lint_auto 17 | ament_lint_common 18 | 19 | 20 | ament_cmake 21 | 22 | 23 | -------------------------------------------------------------------------------- /simple-listener-dl-cpp/src/app/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | app 5 | 2.3.0 6 | Simple ROS 2 subscriber (listener) in cpp 7 | boschrexroth 8 | MIT License 9 | 10 | ament_cmake 11 | 12 | rclcpp 13 | std_msgs 14 | sensor_msgs 15 | 16 | ament_lint_auto 17 | ament_lint_common 18 | 19 | 20 | ament_cmake 21 | 22 | 23 | -------------------------------------------------------------------------------- /simple-listener-dl-py/src/app/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | app 5 | 2.2.0 6 | The package demonstrate a ROS2 listener 7 | boschrexroth 8 | MIT Licence 9 | 10 | ament_copyright 11 | ament_flake8 12 | ament_pep257 13 | python3-pytest 14 | rclpy 15 | std_msgs 16 | 17 | 18 | ament_python 19 | 20 | 21 | -------------------------------------------------------------------------------- /simple-talker-dl-py/src/app/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | app 5 | 2.2.0 6 | The package demonstrate a simple ROS2 talker (publisher) 7 | boschrexroth 8 | MIT Licence 9 | 10 | ament_copyright 11 | ament_flake8 12 | ament_pep257 13 | python3-pytest 14 | rclpy 15 | std_msgs 16 | 17 | 18 | ament_python 19 | 20 | 21 | -------------------------------------------------------------------------------- /simple-talker-py/src/talker/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | talker 5 | 0.0.0 6 | The package demonstrate a simple ROS2 talker (publisher) 7 | boschrexroth 8 | MIT Licence 9 | 10 | ament_copyright 11 | ament_flake8 12 | ament_pep257 13 | python3-pytest 14 | rclpy 15 | std_msgs 16 | 17 | 18 | 19 | ament_python 20 | 21 | 22 | -------------------------------------------------------------------------------- /simple-listener-py/src/listener/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | listener 5 | 0.0.0 6 | The package demonstrate a simple ROS2 subscriber (listener) 7 | boschrexroth 8 | MIT Licence 9 | 10 | ament_copyright 11 | ament_flake8 12 | ament_pep257 13 | python3-pytest 14 | rclpy 15 | std_msgs 16 | 17 | 18 | 19 | ament_python 20 | 21 | 22 | -------------------------------------------------------------------------------- /simple-talker-dl-cpp/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "tasks": [ 3 | { 4 | "type": "cppbuild", 5 | "label": "C/C++: gcc build active file", 6 | "command": "/usr/bin/gcc", 7 | "args": [ 8 | "-fdiagnostics-color=always", 9 | "-g", 10 | "${file}", 11 | "-o", 12 | "${fileDirname}/${fileBasenameNoExtension}" 13 | ], 14 | "options": { 15 | "cwd": "${fileDirname}" 16 | }, 17 | "problemMatcher": [ 18 | "$gcc" 19 | ], 20 | "group": { 21 | "kind": "build", 22 | "isDefault": true 23 | }, 24 | "detail": "Task generated by Debugger." 25 | } 26 | ], 27 | "version": "2.0.0" 28 | } -------------------------------------------------------------------------------- /simple-listener-dl-cpp/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "tasks": [ 3 | { 4 | "type": "cppbuild", 5 | "label": "C/C++: gcc build active file", 6 | "command": "/usr/bin/gcc", 7 | "args": [ 8 | "-fdiagnostics-color=always", 9 | "-g", 10 | "${file}", 11 | "-o", 12 | "${fileDirname}/${fileBasenameNoExtension}" 13 | ], 14 | "options": { 15 | "cwd": "${fileDirname}" 16 | }, 17 | "problemMatcher": [ 18 | "$gcc" 19 | ], 20 | "group": { 21 | "kind": "build", 22 | "isDefault": true 23 | }, 24 | "detail": "Task generated by Debugger." 25 | } 26 | ], 27 | "version": "2.0.0" 28 | } -------------------------------------------------------------------------------- /simple-listener-dl-py/wrapper/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | export ROS_BASE=$SNAP/rosruntime 3 | export PYTHONPATH=$PYTHONPATH:$ROS_BASE/lib/python3.10/site-packages 4 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/lib 5 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/lib/$TRIPLET 6 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/usr/lib 7 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/usr/include/comm/datalayer/ 8 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/usr/lib/x86_64-linux-gnu/ 9 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/usr/lib/$TRIPLET 10 | 11 | export PATH=${PATH}:${ROS_BASE}/opt/ros/humble/bin 12 | export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${ROS_BASE}/opt/ros/humble/lib 13 | 14 | source $ROS_BASE/opt/ros/humble/setup.bash #source if ros2 using debian package is build as a snap 15 | #source $ROS_BASE/setup.bash #source if ros2 is built from source 16 | source $SNAP/local_setup.bash && $SNAP/app/lib/app/app 17 | -------------------------------------------------------------------------------- /simple-talker-cpp/wrapper/run-talker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | export ROS_BASE=$SNAP/rosruntime 3 | export PYTHONPATH=$PYTHONPATH:$ROS_BASE/lib/python3.10/site-packages 4 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/lib 5 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/lib/$TRIPLET 6 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/usr/lib 7 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/usr/include/comm/datalayer/ 8 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/usr/lib/x86_64-linux-gnu/ 9 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/usr/lib/$TRIPLET 10 | 11 | export PATH=${PATH}:${ROS_BASE}/opt/ros/humble/bin 12 | export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${ROS_BASE}/opt/ros/humble/lib 13 | 14 | source $ROS_BASE/opt/ros/humble/setup.bash #source if ros2 using debian package is build as a snap 15 | #source $ROS_BASE/setup.bash #source if ros2 is built from source 16 | source $SNAP/local_setup.bash && $SNAP/app/lib/app/talker -------------------------------------------------------------------------------- /simple-talker-dl-py/wrapper/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | export ROS_BASE=$SNAP/rosruntime 3 | export PYTHONPATH=$PYTHONPATH:$ROS_BASE/lib/python3.10/site-packages 4 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/lib 5 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/lib/$TRIPLET 6 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/usr/lib 7 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/usr/include/comm/datalayer/ 8 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/usr/lib/x86_64-linux-gnu/ 9 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/usr/lib/$TRIPLET 10 | 11 | export PATH=${PATH}:${ROS_BASE}/opt/ros/humble/bin 12 | export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${ROS_BASE}/opt/ros/humble/lib 13 | 14 | source $ROS_BASE/opt/ros/humble/setup.bash #source if ros2 using debian package is build as a snap 15 | #source $ROS_BASE/setup.bash #source if ros2 is built from source 16 | source $SNAP/local_setup.bash && $SNAP/app/lib/app/app 17 | -------------------------------------------------------------------------------- /simple-listener-dl-py/src/app/setup.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Bosch Rexroth AG 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | from setuptools import setup 6 | 7 | package_name = 'app' 8 | 9 | setup( 10 | name=package_name, 11 | version='2.2.0', 12 | packages=[package_name, 'ctrlx_datalayer', 'ros2'], 13 | data_files=[ 14 | ('share/ament_index/resource_index/packages', 15 | ['resource/' + package_name]), 16 | ('share/' + package_name, ['package.xml']) 17 | ], 18 | install_requires=['setuptools'], 19 | zip_safe=True, 20 | maintainer='boschrexroth', 21 | maintainer_email='github@boschrexroth.com', 22 | description='Receives ROS2 message and writes the value into the ctrlX Data', 23 | license='MIT Licence', 24 | tests_require=['pytest'], 25 | entry_points={ 26 | 'console_scripts': [ 27 | 'app = app.main:main', 28 | ], 29 | }, 30 | ) 31 | -------------------------------------------------------------------------------- /simple-listener-cpp/wrapper/run-listener.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | export ROS_BASE=$SNAP/rosruntime 3 | export PYTHONPATH=$PYTHONPATH:$ROS_BASE/lib/python3.10/site-packages 4 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/lib 5 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/lib/$TRIPLET 6 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/usr/lib 7 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/usr/include/comm/datalayer/ 8 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/usr/lib/x86_64-linux-gnu/ 9 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/usr/lib/$TRIPLET 10 | 11 | export PATH=${PATH}:${ROS_BASE}/opt/ros/humble/bin 12 | export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${ROS_BASE}/opt/ros/humble/lib 13 | 14 | source $ROS_BASE/opt/ros/humble/setup.bash #source if ros2 using debian package is build as a snap 15 | #source $ROS_BASE/setup.bash #source if ros2 is built from source 16 | source $SNAP/local_setup.bash && $SNAP/app/lib/app/listener -------------------------------------------------------------------------------- /simple-listener-py/wrapper/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | export ROS_BASE=$SNAP/rosruntime 3 | export PYTHONPATH=$PYTHONPATH:$ROS_BASE/lib/python3.10/site-packages 4 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/lib 5 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/lib/$TRIPLET 6 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/usr/lib 7 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/usr/include/comm/datalayer/ 8 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/usr/lib/x86_64-linux-gnu/ 9 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/usr/lib/$TRIPLET 10 | 11 | export PATH=${PATH}:${ROS_BASE}/opt/ros/humble/bin 12 | export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${ROS_BASE}/opt/ros/humble/lib 13 | 14 | source $ROS_BASE/opt/ros/humble/setup.bash #source if ros2 using debian package is build as a snap 15 | #source $ROS_BASE/setup.bash #source if ros2 is built from source 16 | source $SNAP/local_setup.bash && $SNAP/listener/lib/listener/subscriber -------------------------------------------------------------------------------- /simple-talker-dl-cpp/wrapper/run-listener.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | export ROS_BASE=$SNAP/rosruntime 3 | export PYTHONPATH=$PYTHONPATH:$ROS_BASE/lib/python3.10/site-packages 4 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/lib 5 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/lib/$TRIPLET 6 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/usr/lib 7 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/usr/include/comm/datalayer/ 8 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/usr/lib/x86_64-linux-gnu/ 9 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/usr/lib/$TRIPLET 10 | 11 | export PATH=${PATH}:${ROS_BASE}/opt/ros/humble/bin 12 | export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${ROS_BASE}/opt/ros/humble/lib 13 | 14 | source $ROS_BASE/opt/ros/humble/setup.bash #source if ros2 using debian package is build as a snap 15 | #source $ROS_BASE/setup.bash #source if ros2 is built from source 16 | source $SNAP/local_setup.bash && $SNAP/app/lib/app/listener -------------------------------------------------------------------------------- /simple-talker-dl-py/src/app/setup.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Bosch Rexroth AG 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | from setuptools import setup 6 | 7 | package_name = 'app' 8 | 9 | setup( 10 | name=package_name, 11 | version='2.2.0', 12 | packages=[package_name, 'ctrlx_datalayer', 'ros2'], 13 | data_files=[ 14 | ('share/ament_index/resource_index/packages', 15 | ['resource/' + package_name]), 16 | ('share/' + package_name, ['package.xml']) 17 | ], 18 | install_requires=['setuptools'], 19 | zip_safe=True, 20 | maintainer='boschrexroth', 21 | maintainer_email='github@boschrexroth.com', 22 | description='Reads avalue from the ctrlX Data Layer and publishes it as ROS 2 message', 23 | license='MIT Licence', 24 | tests_require=['pytest'], 25 | entry_points={ 26 | 'console_scripts': [ 27 | 'app = app.main:main', 28 | ], 29 | }, 30 | ) 31 | -------------------------------------------------------------------------------- /simple-talker-py/wrapper/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | export ROS_BASE=$SNAP/rosruntime 3 | export PYTHONPATH=$PYTHONPATH:$ROS_BASE/lib/python3.10/site-packages 4 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/lib 5 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/lib/$TRIPLET 6 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/usr/lib 7 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/usr/include/comm/datalayer/ 8 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/usr/lib/x86_64-linux-gnu/ 9 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/usr/lib/$TRIPLET 10 | 11 | export PATH=${PATH}:${ROS_BASE}/opt/ros/humble/bin 12 | export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${ROS_BASE}/opt/ros/humble/lib 13 | 14 | source $ROS_BASE/opt/ros/humble/setup.bash #source if ros2 using debian package is build as a snap 15 | #source $ROS_BASE/setup.bash #source if ros2 is built from source 16 | source $SNAP/local_setup.bash && $SNAP/talker/lib/talker/publisher 17 | -------------------------------------------------------------------------------- /simple-talker-py/src/talker/setup.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Bosch Rexroth AG 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | from setuptools import setup 6 | import os 7 | from glob import glob 8 | package_name = 'talker' 9 | 10 | setup( 11 | name=package_name, 12 | version='0.0.0', 13 | packages=[package_name], 14 | data_files=[ 15 | ('share/ament_index/resource_index/packages', 16 | ['resource/' + package_name]), 17 | ('share/' + package_name, ['package.xml']) 18 | ], 19 | install_requires=['setuptools'], 20 | zip_safe=True, 21 | maintainer='boschrexroth', 22 | maintainer_email="github@boschrexroth.com", 23 | description='The package demonstrate a simple ROS2 talker (publisher)', 24 | license='MIT Licence', 25 | tests_require=['pytest'], 26 | entry_points={ 27 | 'console_scripts': [ 28 | 'publisher = talker.main_minimal_publisher:main', 29 | ], 30 | }, 31 | ) 32 | -------------------------------------------------------------------------------- /scripts/setup-ctrlx-datalayer-deb.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Exit immediately if a command exits with a non-zero status. 4 | #set -e 5 | 6 | ROOT_DIR=$(git rev-parse --show-toplevel) 7 | 8 | echo "rootdir=$ROOT_DIR" 9 | 10 | rm -rf ${ROOT_DIR}/deb 11 | 12 | source ${ROOT_DIR}/scripts/install-ctrlx-datalayer-deb.sh ${1} ${2} 13 | cd ${ROOT_DIR}/deb 14 | 15 | sudo apt-get install -y dpkg-dev 16 | 17 | # Install debian package locally so that 'apt-get install' will find it (for building sample project snaps) 18 | dpkg-scanpackages -m . >Packages 19 | 20 | # Add package to sources list 21 | full_path=$(pwd) 22 | echo "deb [trusted=yes] file:${full_path} ./" | sudo tee /etc/apt/sources.list.d/ctrlx-automation.list 23 | 24 | # Fix the APT Error Download that is performed unsandboxed as root as 25 | echo "APT::Sandbox::User \"root\";" | sudo tee /etc/apt/apt.conf.d/10sandbox 26 | 27 | sudo apt-get update 28 | 29 | # Install newest ctrlx-datalayer package 30 | sudo apt-get install ctrlx-datalayer -y 31 | -------------------------------------------------------------------------------- /simple-listener-dl-py/src/app/app/main.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Bosch Rexroth AG 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | # ROS Client Library for Python 6 | # https://docs.ros2.org/latest/api/rclpy/index.html 7 | import rclpy 8 | 9 | from ros2.ros2_listener_ctrlx_provider import Ros2ListenerDataLayerProvider 10 | 11 | def main(args=None): 12 | """ 13 | The main function. 14 | 15 | Manages usage of the ROS Client Library 16 | """ 17 | rclpy.init(args=args) 18 | 19 | ros2_publisher = Ros2ListenerDataLayerProvider( 20 | dl_address='ros2/listener/py/cpu-utilisation-percent', 21 | ros2_topic='ctrlXCpuUtilisationPercent') 22 | 23 | result = ros2_publisher.start() 24 | if result is False: 25 | ros2_publisher.stop() 26 | ros2_publisher.destroy_node() 27 | return 28 | 29 | rclpy.spin(ros2_publisher) 30 | 31 | ros2_publisher.stop() 32 | ros2_publisher.destroy_node() 33 | rclpy.shutdown() 34 | 35 | 36 | if __name__ == '__main__': 37 | main() 38 | -------------------------------------------------------------------------------- /simple-listener-py/src/listener/setup.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Bosch Rexroth AG 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | from setuptools import setup 6 | import os 7 | from glob import glob 8 | package_name = 'listener' 9 | 10 | setup( 11 | name=package_name, 12 | version='0.0.0', 13 | packages=[package_name], 14 | data_files=[ 15 | ('share/ament_index/resource_index/packages', 16 | ['resource/' + package_name]), 17 | ('share/' + package_name, ['package.xml']), 18 | (os.path.join('share', package_name), glob('*.json')), 19 | ], 20 | install_requires=['setuptools'], 21 | zip_safe=True, 22 | maintainer='boschrexroth', 23 | maintainer_email='github@boschrexroth.com', 24 | description='The package demonstrate a simple ROS2 subscriber (listener)', 25 | license='MIT Licence', 26 | tests_require=['pytest'], 27 | entry_points={ 28 | 'console_scripts': [ 29 | 'subscriber = listener.main_minimal_subscriber:main', 30 | ], 31 | }, 32 | ) -------------------------------------------------------------------------------- /simple-talker-cpp/snap/snapcraft.yaml: -------------------------------------------------------------------------------- 1 | name: ros2-simple-talker-cpp 2 | version: '2.4.0' 3 | summary: Snap with simple ROS 2 talker 4 | description: | 5 | A simple ROS 2 talker publishes messages on topic 'ros2_simple_cpp'. 6 | 7 | base: core22 8 | grade: stable 9 | confinement: strict 10 | type: app 11 | architectures: 12 | - build-on: [amd64, arm64] 13 | build-for: [amd64] 14 | - build-on: [amd64, arm64] 15 | build-for: [arm64] 16 | 17 | parts: 18 | ros-app: 19 | plugin: dump 20 | source: install 21 | 22 | wrapper-scripts: 23 | plugin: dump 24 | source: wrapper/ 25 | organize: 26 | ./run-talker.sh : usr/bin/run-talker 27 | 28 | apps: 29 | talker: 30 | command: usr/bin/run-talker 31 | plugs: 32 | - ros-base 33 | - network 34 | - network-bind 35 | daemon: simple 36 | passthrough: 37 | restart-condition: always 38 | restart-delay: 10s 39 | 40 | plugs: 41 | ros-base: 42 | interface: content 43 | content: executables 44 | target: $SNAP/rosruntime 45 | -------------------------------------------------------------------------------- /simple-listener-dl-cpp/wrapper/run-listener.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | export ROS_BASE=$SNAP/rosruntime 3 | export PYTHONPATH=$PYTHONPATH:$ROS_BASE/lib/python3.10/site-packages 4 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/lib 5 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/lib/$TRIPLET 6 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/usr/lib 7 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/usr/include/comm/datalayer/ 8 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/usr/lib/x86_64-linux-gnu/ 9 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROS_BASE/usr/lib/$TRIPLET 10 | 11 | export PATH=${PATH}:${ROS_BASE}/opt/ros/humble/bin 12 | export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${ROS_BASE}/opt/ros/humble/lib 13 | 14 | #echo "run-listener PATH='${PATH}'" 15 | #echo "run-listener LD_LIBRARY_PATH='${LD_LIBRARY_PATH}'" 16 | 17 | source $ROS_BASE/opt/ros/humble/setup.bash #source if ros2 using debian package is build as a snap 18 | #source $ROS_BASE/setup.bash #source if ros2 is built from source 19 | source $SNAP/local_setup.bash && $SNAP/app/lib/app/listener -------------------------------------------------------------------------------- /simple-talker-dl-py/src/app/app/main.py: -------------------------------------------------------------------------------- 1 | """Reads a ctrlX Data Layer value and sends it via ROS 2 message.""" 2 | 3 | # SPDX-FileCopyrightText: Bosch Rexroth AG 4 | # 5 | # SPDX-License-Identifier: MIT 6 | 7 | # ROS Client Library for Python 8 | # https://docs.ros2.org/latest/api/rclpy/index.html 9 | import rclpy 10 | 11 | from ros2.datalayer_reader_ros2_publisher import DataLayerReaderRos2Publisher 12 | 13 | 14 | def main(args=None): 15 | """Manage the usage of the ROS Client Library.""" 16 | rclpy.init(args=args) 17 | 18 | ros2_publisher = DataLayerReaderRos2Publisher( 19 | dl_address='framework/metrics/system/cpu-utilisation-percent', 20 | ros2_topic='ctrlXCpuUtilisationPercent') 21 | 22 | result = ros2_publisher.start() 23 | if result is False: 24 | ros2_publisher.stop() 25 | ros2_publisher.destroy_node() 26 | return 27 | 28 | rclpy.spin(ros2_publisher) 29 | 30 | ros2_publisher.stop() 31 | ros2_publisher.destroy_node() 32 | rclpy.shutdown() 33 | 34 | 35 | if __name__ == '__main__': 36 | main() 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Bosch Rexroth AG 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /scripts/README.md: -------------------------------------------------------------------------------- 1 | # Scrips Description 2 | 3 | ## Installation Scripts Files 4 | 5 | * __setup-ctrlx-datalayer-deb.sh__ installs the ctrlx-datalayer Debian package and registers its storage directory as local package source 6 | * __install-ctrlx-datalayer-deb.sh__ installs the ctrlx-datalayer Debian package, see [ctrlX AUTOMATION SDK/Releases](https://github.com/boschrexroth/ctrlx-automation-sdk/releases) 7 | * __setup-system-humble-jammy.sh__ installs the ROS2 Humble development environment [Install Ubuntu (deb packages)](https://docs.ros.org/en/humble/Installation/Ubuntu-Install-Debs.html) 8 | 9 | ``` bash 10 | # install default debian package 11 | ./install-ctrlx-datalayer-deb.sh 12 | ``` 13 | 14 | ``` bash 15 | # install from SDK version 3.2.0 debian package version 2.7.5 16 | ./install-ctrlx-datalayer-deb.sh 3.2.0 2.7.5 17 | ``` 18 | 19 | ## Build Scripts Files 20 | 21 | * __colcon-build.sh__ helper script for colon build, base on ROS2 __Humble__ 22 | * __build-snap-cpp.sh__ helper script for creating snaps based on c++ projects 23 | * __build-snap-py.sh__ Help script for creating snaps based on python projects 24 | 25 | SPDX-License-Identifier: MIT 26 | -------------------------------------------------------------------------------- /simple-talker-cpp/src/app/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.8) 2 | project(app) 3 | 4 | if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") 5 | add_compile_options(-Wall -Wextra -Wpedantic) 6 | endif() 7 | 8 | # find dependencies 9 | find_package(ament_cmake REQUIRED) 10 | find_package(rclcpp REQUIRED) 11 | find_package(std_msgs REQUIRED) 12 | 13 | if(BUILD_TESTING) 14 | find_package(ament_lint_auto REQUIRED) 15 | # the following line skips the linter which checks for copyrights 16 | # comment the line when a copyright and license is added to all source files 17 | set(ament_cmake_copyright_FOUND TRUE) 18 | # the following line skips cpplint (only works in a git repo) 19 | # comment the line when this package is in a git repo and when 20 | # a copyright and license is added to all source files 21 | set(ament_cmake_cpplint_FOUND TRUE) 22 | ament_lint_auto_find_test_dependencies() 23 | endif() 24 | 25 | add_executable(talker src/publisher_member_function.cpp) 26 | ament_target_dependencies(talker rclcpp std_msgs) 27 | 28 | install(TARGETS 29 | talker 30 | DESTINATION lib/${PROJECT_NAME}) 31 | 32 | ament_package() 33 | -------------------------------------------------------------------------------- /simple-listener-cpp/src/app/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.8) 2 | project(app) 3 | 4 | if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") 5 | add_compile_options(-Wall -Wextra -Wpedantic) 6 | endif() 7 | 8 | # find dependencies 9 | find_package(ament_cmake REQUIRED) 10 | find_package(rclcpp REQUIRED) 11 | find_package(std_msgs REQUIRED) 12 | 13 | if(BUILD_TESTING) 14 | find_package(ament_lint_auto REQUIRED) 15 | # the following line skips the linter which checks for copyrights 16 | # comment the line when a copyright and license is added to all source files 17 | set(ament_cmake_copyright_FOUND TRUE) 18 | # the following line skips cpplint (only works in a git repo) 19 | # comment the line when this package is in a git repo and when 20 | # a copyright and license is added to all source files 21 | set(ament_cmake_cpplint_FOUND TRUE) 22 | ament_lint_auto_find_test_dependencies() 23 | endif() 24 | 25 | add_executable(listener src/subscriber_member_function.cpp) 26 | ament_target_dependencies(listener rclcpp std_msgs) 27 | 28 | install(TARGETS 29 | listener 30 | DESTINATION lib/${PROJECT_NAME}) 31 | 32 | ament_package() 33 | -------------------------------------------------------------------------------- /simple-listener-cpp/snap/snapcraft.yaml: -------------------------------------------------------------------------------- 1 | name: ros2-simple-listener-cpp 2 | version: '2.4.0' 3 | summary: Snap with simple ROS 2 listener 4 | description: | 5 | A simple ROS 2 listener which receives ROS 2 messages on topic 'ros2_simple_cpp'. 6 | 7 | base: core22 8 | grade: stable 9 | confinement: strict 10 | type: app 11 | 12 | architectures: 13 | - build-on: [amd64, arm64] 14 | build-for: [amd64] 15 | - build-on: [amd64, arm64] 16 | build-for: [arm64] 17 | 18 | parts: 19 | ros-app: 20 | plugin: dump 21 | source: install 22 | override-build: | 23 | craftctl default 24 | 25 | wrapper-scripts: 26 | plugin: dump 27 | source: wrapper/ 28 | organize: 29 | ./run-listener.sh : usr/bin/run-listener 30 | 31 | apps: 32 | listener: 33 | command: usr/bin/run-listener 34 | plugs: 35 | - ros-base 36 | - network 37 | - network-bind 38 | daemon: simple 39 | passthrough: 40 | restart-condition: always 41 | restart-delay: 10s 42 | 43 | plugs: 44 | ros-base: 45 | interface: content 46 | content: executables 47 | target: $SNAP/rosruntime 48 | 49 | lint: 50 | ignore: 51 | - library 52 | -------------------------------------------------------------------------------- /simple-listener-py/src/listener/listener/main_minimal_subscriber.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Bosch Rexroth AG 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | import rclpy 6 | from rclpy.node import Node 7 | 8 | from std_msgs.msg import String 9 | 10 | 11 | class MinimalSubscriber(Node): 12 | 13 | def __init__(self): 14 | super().__init__('minimal_subscriber') 15 | self.subscription = self.create_subscription( 16 | String, 17 | 'MinimalPublisher', 18 | self.listener_callback, 19 | 10) 20 | self.subscription # prevent unused variable warning 21 | 22 | def listener_callback(self, msg): 23 | self.get_logger().info('I heard: "%s"' % msg.data) 24 | 25 | 26 | def main(args=None): 27 | rclpy.init(args=args) 28 | 29 | minimal_subscriber = MinimalSubscriber() 30 | 31 | rclpy.spin(minimal_subscriber) 32 | 33 | # Destroy the node explicitly 34 | # (optional - otherwise it will be done automatically 35 | # when the garbage collector destroys the node object) 36 | minimal_subscriber.destroy_node() 37 | 38 | rclpy.shutdown() 39 | 40 | 41 | if __name__ == '__main__': 42 | main() -------------------------------------------------------------------------------- /simple-listener-py/snap/snapcraft.yaml: -------------------------------------------------------------------------------- 1 | name: ros2-simple-listener 2 | version: '2.4.0' 3 | summary: Simple ROS 2 listener 4 | description: | 5 | A simple ROS 2 listener to ROS 2 topic 'MinimalPublisher'. 6 | 7 | base: core22 8 | grade: stable 9 | confinement: strict 10 | type: app 11 | 12 | architectures: 13 | - build-on: [amd64, arm64] 14 | build-for: [amd64] 15 | - build-on: [amd64, arm64] 16 | build-for: [arm64] 17 | 18 | parts: 19 | ros-app: 20 | plugin: dump 21 | source: install 22 | stage-packages: [libpython3.10] 23 | override-build: | 24 | craftctl default 25 | 26 | wrapper-scripts: 27 | plugin: dump 28 | source: wrapper/ 29 | organize: 30 | ./run.sh : usr/bin/run 31 | 32 | apps: 33 | subscriber: 34 | command: usr/bin/run 35 | plugs: 36 | - ros-base 37 | - network 38 | - network-bind 39 | daemon: simple 40 | passthrough: 41 | restart-condition: always 42 | restart-delay: 10s 43 | 44 | plugs: 45 | ros-base: 46 | interface: content 47 | content: executables 48 | target: $SNAP/rosruntime 49 | 50 | lint: 51 | ignore: 52 | - library: 53 | - usr/lib/x86_64-linux-gnu/libpython3.10.so.* -------------------------------------------------------------------------------- /LICENSES/MIT.txt: -------------------------------------------------------------------------------- 1 | This license applies only to the code in this repository. 2 | Images, fonts and other assets are explicitly excluded. 3 | 4 | MIT License 5 | 6 | Copyright (c) Bosch Rexroth AG 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | -------------------------------------------------------------------------------- /simple-talker-dl-cpp/snap/snapcraft.yaml: -------------------------------------------------------------------------------- 1 | name: ros2-simple-talker-dl-cpp 2 | version: '2.4.0' 3 | summary: Snap with simple ROS 2 listener 4 | description: | 5 | A simple ROS 2 listener which receives ROS 2 messages on topic 'ros2_simple_cpp'. 6 | 7 | base: core22 8 | grade: stable 9 | confinement: strict 10 | type: app 11 | architectures: 12 | - build-on: [amd64, arm64] 13 | build-for: [amd64] 14 | - build-on: [amd64, arm64] 15 | build-for: [arm64] 16 | 17 | parts: 18 | ros-app: 19 | plugin: dump 20 | source: install 21 | stage-packages: 22 | - ctrlx-datalayer 23 | override-build: | 24 | craftctl default 25 | 26 | wrapper-scripts: 27 | plugin: dump 28 | source: wrapper/ 29 | organize: 30 | ./run-listener.sh : usr/bin/run-listener 31 | 32 | apps: 33 | listener: 34 | command: usr/bin/run-listener 35 | plugs: 36 | - ros-base 37 | - network 38 | - network-bind 39 | daemon: simple 40 | passthrough: 41 | restart-condition: always 42 | restart-delay: 10s 43 | 44 | plugs: 45 | ros-base: 46 | interface: content 47 | content: executables 48 | target: $SNAP/rosruntime 49 | 50 | datalayer: 51 | interface: content 52 | content: datalayer 53 | target: $SNAP_DATA/.datalayer 54 | -------------------------------------------------------------------------------- /simple-talker-py/src/talker/talker/main_minimal_publisher.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Bosch Rexroth AG 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | import rclpy 6 | from rclpy.node import Node 7 | 8 | from std_msgs.msg import String 9 | 10 | 11 | class MinimalPublisher(Node): 12 | 13 | def __init__(self): 14 | 15 | super().__init__('MinimalPublisher') 16 | 17 | self.publisher_ = self.create_publisher(String, 'MinimalPublisher', 10) 18 | timer_period = 0.5 # seconds 19 | self.timer = self.create_timer(timer_period, self.timer_callback) 20 | self.i = 0 21 | 22 | def timer_callback(self): 23 | 24 | msg = String() 25 | msg.data = 'Hello World: %d' % self.i 26 | self.publisher_.publish(msg) 27 | self.get_logger().info('Publishing: "%s"' % msg.data) 28 | self.i += 1 29 | 30 | 31 | 32 | def main(args=None): 33 | rclpy.init(args=args) 34 | 35 | minimal_publisher = MinimalPublisher() 36 | 37 | rclpy.spin(minimal_publisher) 38 | 39 | # Destroy the node explicitly 40 | # (optional - otherwise it will be done automatically 41 | # when the garbage collector destroys the node object) 42 | minimal_publisher.destroy_node() 43 | 44 | rclpy.shutdown() 45 | 46 | if __name__ == '__main__': 47 | main() 48 | -------------------------------------------------------------------------------- /simple-talker-py/snap/snapcraft.yaml: -------------------------------------------------------------------------------- 1 | name: ros2-simple-talker-py 2 | version: '2.4.0' 3 | summary: Simple ROS 2 talker 4 | description: | 5 | A simple ROS 2 talker to ROS 2 topic 'MinimalPublisher'. 6 | 7 | base: core22 8 | grade: devel # must be 'stable' to release into candidate/stable channels 9 | confinement: strict 10 | type: app 11 | 12 | architectures: 13 | - build-on: [amd64, arm64] 14 | build-for: [amd64] 15 | - build-on: [amd64, arm64] 16 | build-for: [arm64] 17 | 18 | parts: 19 | # The `source` here is the tarred staging area of the ros-base snap. 20 | ros-app: 21 | plugin: dump 22 | source: install 23 | stage-packages: [libpython3.10] 24 | override-build: | 25 | craftctl default 26 | 27 | wrapper-scripts: 28 | plugin: dump 29 | source: wrapper/ 30 | organize: 31 | ./run.sh : usr/bin/run 32 | 33 | apps: 34 | publisher: 35 | command: usr/bin/run 36 | plugs: 37 | - ros-base 38 | - network 39 | - network-bind 40 | daemon: simple 41 | passthrough: 42 | restart-condition: always 43 | restart-delay: 10s 44 | 45 | plugs: 46 | ros-base: 47 | interface: content 48 | content: executables 49 | target: $SNAP/rosruntime 50 | 51 | lint: 52 | ignore: 53 | - library: 54 | - usr/lib/x86_64-linux-gnu/libpython3.10.so.* -------------------------------------------------------------------------------- /scripts/install-snapcraft.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | etc_environment=$(cat /etc/environment) 4 | if [[ ${etc_environment} != *"SNAPCRAFT_BUILD_ENVIRONMENT=host"* ]];then 5 | sudo echo "SNAPCRAFT_BUILD_ENVIRONMENT=host" | sudo tee -a /etc/environment 6 | fi 7 | 8 | if [[ ${etc_environment} != *"SNAPCRAFT_ENABLE_EXPERIMENTAL_TARGET_ARCH=1"* ]];then 9 | sudo echo "SNAPCRAFT_ENABLE_EXPERIMENTAL_TARGET_ARCH=1" | sudo tee -a /etc/environment 10 | fi 11 | 12 | function install_snapcraft() { 13 | echo "" 14 | echo "-------------------------------------------------------" 15 | echo "install snapcraft 7.x" 16 | echo "-------------------------------------------------------" 17 | echo "" 18 | 19 | sudo snap install snapcraft --channel=7.x/stable --classic 20 | } 21 | 22 | # Avoid return or exit, so that thsi sscript can be called from elsewhere 23 | 24 | snap_list=$(snap list) 25 | if [[ ${snap_list} != *"snapcraft"* ]];then 26 | # snapcraft is not installed, so install it 27 | install_snapcraft 28 | else 29 | # snapcraft is installed 30 | snapcraft_installed=$(snap list snapcraft) 31 | if [[ ${snapcraft_installed} != *"7."* ]];then 32 | # but not the desired version, so remove this versin and install the right one 33 | echo Uninstalling inappropriate snapcraft version... 34 | sudo snap remove snapcraft 2>/dev/null 35 | install_snapcraft 36 | fi 37 | fi 38 | 39 | -------------------------------------------------------------------------------- /ros2-base-humble-deb/snap/snapcraft.yaml: -------------------------------------------------------------------------------- 1 | name: ros2-base-humble 2 | version: '2.4.0' 3 | summary: ROS 2 Humble base snap for ctrlX CORE 4 | description: | 5 | Provides ROS 2 Humble for ROS 2 applications running on a for ctrlX CORE. 6 | 7 | base: core22 8 | grade: stable 9 | confinement: strict 10 | type: app 11 | 12 | architectures: 13 | - build-on: [amd64, arm64] 14 | build-for: [amd64] 15 | - build-on: [amd64, arm64] 16 | build-for: [arm64] 17 | 18 | parts: 19 | ros-base: 20 | plugin: colcon 21 | build-packages: [make, gcc, g++] 22 | stage-packages: [ 23 | software-properties-common, 24 | ros-humble-ros-base, 25 | python3-argcomplete, 26 | ca-certificates 27 | ] 28 | build-environment: 29 | - ROS_VERSION: '2' 30 | - ROS_DISTRO: humble 31 | source: ./ 32 | 33 | datalayer: 34 | plugin: nil 35 | stage-packages: 36 | - ctrlx-datalayer 37 | 38 | helper: 39 | plugin: python 40 | build-environment: 41 | - PYTHONPATH: "$CRAFT_PART_INSTALL/usr/lib/python3/dist-packages" 42 | stage-packages: 43 | - python3-wheel 44 | - python3.10-venv 45 | python-packages: 46 | - ctrlx-datalayer 47 | - empy 48 | - numpy 49 | - rosdep 50 | - rosdistro 51 | - colcon-core 52 | - lark 53 | source: ./ 54 | 55 | slots: 56 | ros-base: 57 | interface: content 58 | content: executables 59 | read: [/] 60 | -------------------------------------------------------------------------------- /simple-listener-dl-cpp/snap/snapcraft.yaml: -------------------------------------------------------------------------------- 1 | name: ros2-simple-listener-dl-cpp 2 | version: '2.4.0' 3 | summary: Snap with simple ROS 2 listener 4 | description: | 5 | A simple ROS 2 listener which receives ROS 2 messages on topic 'ros2_simple_cpp'. 6 | 7 | base: core22 8 | grade: stable 9 | confinement: strict 10 | type: app 11 | 12 | architectures: 13 | - build-on: [amd64, arm64] 14 | build-for: [amd64] 15 | - build-on: [amd64, arm64] 16 | build-for: [arm64] 17 | 18 | parts: 19 | ros-app: 20 | plugin: dump 21 | source: install 22 | stage-packages: 23 | - ctrlx-datalayer 24 | override-build: | 25 | craftctl default 26 | 27 | wrapper-scripts: 28 | plugin: dump 29 | source: wrapper/ 30 | organize: 31 | ./run-listener.sh : usr/bin/run-listener 32 | 33 | apps: 34 | listener: 35 | command: usr/bin/run-listener 36 | plugs: 37 | - ros-base 38 | - network 39 | - network-bind 40 | daemon: simple 41 | passthrough: 42 | restart-condition: always 43 | restart-delay: 10s 44 | 45 | plugs: 46 | ros-base: 47 | interface: content 48 | content: executables 49 | target: $SNAP/rosruntime 50 | 51 | datalayer: 52 | interface: content 53 | content: datalayer 54 | target: $SNAP_DATA/.datalayer 55 | 56 | lint: 57 | ignore: 58 | - library: 59 | - usr/lib/aarch64-linux-gnu/libcomm_datalayer.so.* 60 | - usr/lib/x86_64-linux-gnu/libcomm_datalayer.so.* 61 | -------------------------------------------------------------------------------- /simple-talker-dl-py/snap/snapcraft.yaml: -------------------------------------------------------------------------------- 1 | name: ros2-talker-dl-py 2 | version: '2.4.0' 3 | summary: Publishes ctrlX Data Layer value to ROS 2 4 | description: | 5 | A ROS 2 talker: 6 | Reads ctrlX Data Layer value framework/metrics/system/cpu-utilisation-percent 7 | and publishes it to ROS 2 topic 'ctrlXCpuUtilisationPercent'. 8 | 9 | base: core22 10 | grade: devel # must be 'stable' to release into candidate/stable channels 11 | confinement: strict 12 | type: app 13 | 14 | architectures: 15 | - build-on: [amd64, arm64] 16 | build-for: [amd64] 17 | - build-on: [amd64, arm64] 18 | build-for: [arm64] 19 | 20 | parts: 21 | # The `source` here is the tarred staging area of the ros-base snap. 22 | ros-app: 23 | plugin: dump 24 | source: install 25 | stage-packages: [libpython3.10] 26 | override-build: | 27 | craftctl default 28 | 29 | wrapper-scripts: 30 | plugin: dump 31 | source: wrapper/ 32 | organize: 33 | ./run.sh : usr/bin/run 34 | 35 | apps: 36 | publisher: 37 | command: usr/bin/run 38 | plugs: 39 | - ros-base 40 | - network 41 | - network-bind 42 | daemon: simple 43 | passthrough: 44 | restart-condition: always 45 | restart-delay: 10s 46 | 47 | plugs: 48 | ros-base: 49 | interface: content 50 | content: executables 51 | target: $SNAP/rosruntime 52 | datalayer: 53 | interface: content 54 | content: datalayer 55 | target: $SNAP_DATA/.datalayer 56 | 57 | lint: 58 | ignore: 59 | - library: 60 | - usr/lib/x86_64-linux-gnu/libpython3.10.so.* -------------------------------------------------------------------------------- /simple-listener-dl-py/snap/snapcraft.yaml: -------------------------------------------------------------------------------- 1 | name: ros2-listener-dl-py 2 | version: '2.4.0' 3 | summary: ROS 2 listener stores a received ROS 2 message into a ctrlX Data Layer node 4 | description: | 5 | A ROS 2 listener: 6 | Receives a ROS 2 message and writes it into the ctrlX Data Layer node 7 | ros2/listener-dl/cpu-utilisation-percent. 8 | 9 | base: core22 10 | grade: devel # must be 'stable' to release into candidate/stable channels 11 | confinement: strict 12 | type: app 13 | 14 | architectures: 15 | - build-on: [amd64, arm64] 16 | build-for: [amd64] 17 | - build-on: [amd64, arm64] 18 | build-for: [arm64] 19 | 20 | parts: 21 | # The `source` here is the tarred staging area of the ros-base snap. 22 | ros-app: 23 | plugin: dump 24 | source: install 25 | stage-packages: [libpython3.10] 26 | override-build: | 27 | craftctl default 28 | 29 | wrapper-scripts: 30 | plugin: dump 31 | source: wrapper/ 32 | organize: 33 | ./run.sh : usr/bin/run 34 | 35 | apps: 36 | publisher: 37 | command: usr/bin/run 38 | plugs: 39 | - ros-base 40 | - network 41 | - network-bind 42 | daemon: simple 43 | passthrough: 44 | restart-condition: always 45 | restart-delay: 10s 46 | 47 | plugs: 48 | ros-base: 49 | interface: content 50 | content: executables 51 | target: $SNAP/rosruntime 52 | datalayer: 53 | interface: content 54 | content: datalayer 55 | target: $SNAP_DATA/.datalayer 56 | 57 | lint: 58 | ignore: 59 | - library: 60 | - usr/lib/x86_64-linux-gnu/libpython3.10.so.* 61 | -------------------------------------------------------------------------------- /simple-listener-cpp/src/app/src/subscriber_member_function.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | 18 | #include "rclcpp/rclcpp.hpp" 19 | #include "std_msgs/msg/string.hpp" 20 | 21 | using std::placeholders::_1; 22 | 23 | class MinimalSubscriber : public rclcpp::Node 24 | { 25 | public: 26 | MinimalSubscriber() 27 | : Node("minimal_subscriber") 28 | { 29 | m_subscription = this->create_subscription( 30 | "ros2_simple_talker_cpp", 10, std::bind(&MinimalSubscriber::topic_callback, this, _1)); 31 | } 32 | 33 | private: 34 | void topic_callback(const std_msgs::msg::String & msg) const 35 | { 36 | RCLCPP_INFO(this->get_logger(), "I heard: '%s'", msg.data.c_str()); 37 | } 38 | rclcpp::Subscription::SharedPtr m_subscription; 39 | }; 40 | 41 | int main(int argc, char * argv[]) 42 | { 43 | rclcpp::init(argc, argv); 44 | rclcpp::spin(std::make_shared()); 45 | rclcpp::shutdown(); 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | # With this workflow, snaps are created from each example. 2 | 3 | name: Build Snap 4 | 5 | # Controls when the action will run. 6 | on: 7 | # Triggers the workflow on push or pull request events but only for the main branch 8 | push: 9 | branches: [ main ] 10 | pull_request: 11 | branches: [ main ] 12 | 13 | # Allows you to run this workflow manually from the Actions tab 14 | workflow_dispatch: 15 | 16 | jobs: 17 | SetupAndBuild: 18 | #runs-on: ubuntu-latest 19 | runs-on: ubuntu-22.04 20 | strategy: 21 | fail-fast: false 22 | steps: 23 | - name: Setup ROS 24 | uses: ros-tooling/setup-ros@v0.7 25 | env: 26 | SNAPCRAFT_BUILD_ENVIRONMENT: host 27 | SNAPCRAFT_ENABLE_EXPERIMENTAL_TARGET_ARCH: 1 28 | - run: vcs --help 29 | 30 | - name: Checkout 31 | uses: actions/checkout@v4 32 | with: 33 | fetch-depth: 0 34 | 35 | - name: Install snapcraft 36 | run: sudo snap install snapcraft --channel=7.x/stable --classic 37 | 38 | - name: Update ROS development 39 | run: rosdep update 40 | 41 | - name: Set up Snapcraft env 42 | run: | 43 | echo "SNAPCRAFT_BUILD_ENVIRONMENT=host" >> "$GITHUB_ENV" 44 | echo "SNAPCRAFT_ENABLE_EXPERIMENTAL_TARGET_ARCH=1" >> "$GITHUB_ENV" 45 | 46 | - run: | 47 | cd simple-listener-py 48 | ./build-snap-amd64.sh 49 | - run: | 50 | cd simple-listener-cpp 51 | ./build-snap-amd64.sh 52 | - run: | 53 | cd simple-listener-dl-py 54 | ./build-snap-amd64.sh 55 | - run: | 56 | cd simple-talker-py 57 | ./build-snap-amd64.sh 58 | - run: | 59 | cd simple-talker-cpp 60 | ./build-snap-amd64.sh 61 | - run: | 62 | cd simple-talker-dl-py 63 | ./build-snap-amd64.sh 64 | -------------------------------------------------------------------------------- /scripts/setup-system-humble-jammy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | # see: https://docs.ros.org/en/humble/Installation/Ubuntu-Install-Debs.html 6 | echo "Setup ROS2 Humble environment" 7 | 8 | # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 9 | # +++++++++ Set locale +++++++++ 10 | # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 11 | echo "-- Set locale" 12 | locale # check for UTF-8 13 | 14 | sudo apt update && sudo apt install locales 15 | sudo locale-gen en_US en_US.UTF-8 16 | sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 17 | export LANG=en_US.UTF-8 18 | 19 | locale # verify settings 20 | 21 | # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 22 | # +++++++++ Setup Sources +++++++++ 23 | # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 24 | echo "-- Add the ROS 2 apt repository" 25 | 26 | sudo apt install software-properties-common 27 | sudo add-apt-repository universe -y 28 | 29 | ## Now add the ROS 2 GPG key with apt. 30 | sudo apt update && sudo apt install curl -y 31 | sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg 32 | 33 | ## Then add the repository to your sources list. 34 | echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null 35 | 36 | # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 37 | # +++++++++ Install ROS 2 packages +++++++++ 38 | # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 39 | echo "-- Install ROS 2 packages" 40 | sudo apt update && sudo apt upgrade -y 41 | 42 | ## ROS-Base Install (Bare Bones): Communication libraries, message packages, command line tools. No GUI tools. 43 | sudo apt install -y ros-humble-ros-base 44 | 45 | ## Development tools: Compilers and other tools to build ROS packages 46 | sudo apt install -y ros-dev-tools 47 | 48 | -------------------------------------------------------------------------------- /simple-talker-cpp/src/app/src/publisher_member_function.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "rclcpp/rclcpp.hpp" 21 | #include "std_msgs/msg/string.hpp" 22 | 23 | using namespace std::chrono_literals; 24 | 25 | /* This example creates a subclass of Node and uses std::bind() to register a 26 | * member function as a callback from the timer. */ 27 | 28 | class MinimalPublisher : public rclcpp::Node 29 | { 30 | rclcpp::TimerBase::SharedPtr m_timer; 31 | rclcpp::Publisher::SharedPtr m_publisher; 32 | size_t m_count; 33 | 34 | public: 35 | MinimalPublisher() 36 | : Node("minimal_publisher"), m_count(0) 37 | { 38 | m_publisher = this->create_publisher("ros2_simple_talker_cpp", 10); 39 | m_timer = this->create_wall_timer( 40 | 500ms, std::bind(&MinimalPublisher::timer_callback, this)); 41 | } 42 | 43 | private: 44 | void timer_callback() 45 | { 46 | auto message = std_msgs::msg::String(); 47 | message.data = "Hello, world! " + std::to_string(m_count++); 48 | RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message.data.c_str()); 49 | m_publisher->publish(message); 50 | } 51 | }; 52 | 53 | int main(int argc, char * argv[]) 54 | { 55 | rclcpp::init(argc, argv); 56 | rclcpp::spin(std::make_shared()); 57 | rclcpp::shutdown(); 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /simple-talker-dl-cpp/src/app/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.8) 2 | project(app) 3 | set(TARGET_PROJECT_NAME listener) 4 | 5 | if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") 6 | add_compile_options(-Wall -Wextra -Wpedantic) 7 | endif() 8 | 9 | # find dependencies 10 | find_package(ament_cmake REQUIRED) 11 | find_package(rclcpp REQUIRED) 12 | find_package(std_msgs REQUIRED) 13 | 14 | 15 | # 16 | # Set link directories 17 | # 18 | MESSAGE( STATUS "Libraries directory: ${LIBRARY_DIR}") 19 | link_directories( 20 | ${LIBRARY_DIR} 21 | ${LIBRARY_DEP_DIR} 22 | ) 23 | 24 | # User dependency directory 25 | # 26 | set (USER_DEPENDENCY_DIR ${CMAKE_CURRENT_LIST_DIR}/../../../..) 27 | 28 | SET ( PRIVATE_INCLUDE_DIRS 29 | ${CMAKE_CURRENT_LIST_DIR} 30 | ${CMAKE_CURRENT_BINARY_DIR} 31 | ${CMAKE_CURRENT_LIST_DIR}/include 32 | ${USER_DEPENDENCY_DIR}/include 33 | ${USER_DEPENDENCY_DIR}/include/comm.datalayer 34 | ) 35 | 36 | # Set target link libraries 37 | 38 | 39 | if(BUILD_TESTING) 40 | find_package(ament_lint_auto REQUIRED) 41 | # the following line skips the linter which checks for copyrights 42 | # comment the line when a copyright and license is added to all source files 43 | set(ament_cmake_copyright_FOUND TRUE) 44 | # the following line skips cpplint (only works in a git repo) 45 | # comment the line when this package is in a git repo and when 46 | # a copyright and license is added to all source files 47 | set(ament_cmake_cpplint_FOUND TRUE) 48 | ament_lint_auto_find_test_dependencies() 49 | endif() 50 | 51 | add_executable(listener src/subscriber_member_function.cpp) 52 | ament_target_dependencies(listener rclcpp std_msgs) 53 | 54 | 55 | # 56 | # Set target include directories 57 | # 58 | target_include_directories ( ${TARGET_PROJECT_NAME} 59 | PUBLIC ${PUBLIC_INCLUDE_DIRS} 60 | PUBLIC ${LIBRARY_INCLUDES} 61 | PRIVATE ${PRIVATE_INCLUDE_DIRS} 62 | ) 63 | # 64 | target_link_libraries(${TARGET_PROJECT_NAME} -Wl,--no-undefined) 65 | target_link_libraries(${TARGET_PROJECT_NAME} 66 | libcomm_datalayer.so 67 | pthread 68 | ssl 69 | crypto 70 | ) 71 | 72 | install(TARGETS 73 | listener 74 | DESTINATION lib/${PROJECT_NAME}) 75 | 76 | ament_package() 77 | -------------------------------------------------------------------------------- /simple-talker-cpp/README.md: -------------------------------------------------------------------------------- 1 | # Simple ROS 2 Publisher in C++ 2 | 3 | ROS 2 node which publishes messages under the topic `ros2_simple_cpp`. 4 | 5 | ## Prerequisites 6 | 7 | * `ros-base` snap. The base snap which provides the ROS 2 runtime binaries. Has to be installed on ctrlX OS. See [ROS 2 Humble Base Snap](../ros2-base-humble-deb/README.md). 8 | * An Ubuntu based build environment to build an app. See [ctrlX Automation SDK](https://github.com/boschrexroth/ctrlx-automation-sdk). 9 | 10 | ## Basis for this Project 11 | 12 | This project is based on the official ROS 2 Tutorial: [Writing a simple publisher and subscriber (C++)](https://docs.ros.org/en/humble/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Cpp-Publisher-And-Subscriber.html#writing-a-simple-publisher-and-subscriber-c). 13 | 14 | ## Building a snap 15 | 16 | Building a snap has two steps: 17 | 18 | 1. Colcon build: CMakeLists.txt defines how compile and link the C++ sources. 19 | 2. snap build: snap/snapcraft.yaml defines how the compiled binaries are packed into the snap and how they are called on the ctrlX CORE. 20 | 21 | ### Colcon Configuration 22 | 23 | The colcon build tool is configured by `CMakeLists.txt`. 24 | 25 | This section defines the ROS 2 packages needed: 26 | 27 | find_package(ament_cmake REQUIRED) 28 | find_package(rclcpp REQUIRED) 29 | find_package(std_msgs REQUIRED) 30 | 31 | And here the executables and their dependencies are defined: 32 | 33 | add_executable(listener src/subscriber_member_function.cpp) 34 | ament_target_dependencies(listener rclcpp std_msgs) 35 | 36 | ### Snapcraft Configuration 37 | 38 | `snap/snapcraft.yaml` defines how the snap will be build: 39 | 40 | * `install/` is dumped into the snap 41 | * also `wrapper/` 42 | * Two apps (talker and listener) are copied into the snap and started as services 43 | * The snap - respectively the executables - uses the content interface of the `ros-base` snap (here the ROS 2 runtime is provided). 44 | 45 | ### Build the snap 46 | 47 | Start this script: 48 | 49 | ./build-snap-amd64.sh 50 | 51 | ## About 52 | 53 | SPDX-FileCopyrightText: Copyright (c) 2023 Bosch Rexroth AG 54 | 55 | 56 | 57 | ## Licenses 58 | 59 | SPDX-License-Identifier: Apache-2.0 60 | -------------------------------------------------------------------------------- /simple-listener-cpp/README.md: -------------------------------------------------------------------------------- 1 | # Simple ROS 2 Subscriber in C++ 2 | 3 | A simple ROS 2 node which subscribes to messages of the topic `ros2_simple_cpp`. 4 | 5 | ## Prerequisites 6 | 7 | * `ros-base` snap. The base snap which provides the ROS 2 runtime binaries. Has to be installed on ctrlX OS. See [ROS 2 Humble Base Snap](../ros2-base-humble-deb/README.md). 8 | * An Ubuntu based build environment to build an app. See [ctrlX Automation SDK](https://github.com/boschrexroth/ctrlx-automation-sdk). 9 | 10 | ## Basis for this Project 11 | 12 | This project is based on the official ROS 2 Tutorial: [Writing a simple publisher and subscriber (C++)](https://docs.ros.org/en/humble/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Cpp-Publisher-And-Subscriber.html#writing-a-simple-publisher-and-subscriber-c). 13 | 14 | ## Building a Snap 15 | 16 | Building a snap has two steps: 17 | 18 | 1. Colcon build: `CMakeLists.txt` defines how compile and link the C++ sources. 19 | 2. snap build: `snap/snapcraft.yaml` defines how the compiled binaries are packed into the snap and how they are called on ctrlX OS. 20 | 21 | ### Colcon Configuration 22 | 23 | The colcon build tool is configured by `CMakeLists.txt`. 24 | 25 | This section defines the ROS 2 packages needed: 26 | 27 | find_package(ament_cmake REQUIRED) 28 | find_package(rclcpp REQUIRED) 29 | find_package(std_msgs REQUIRED) 30 | 31 | And here the executables and their dependencies are defined: 32 | 33 | add_executable(listener src/subscriber_member_function.cpp) 34 | ament_target_dependencies(listener rclcpp std_msgs) 35 | 36 | ### Snapcraft Configuration 37 | 38 | `snap/snapcraft.yaml` defines how the snap will be build: 39 | 40 | * `install/` is dumped into the snap 41 | * also `wrapper/` 42 | * Two apps (talker and listener) are copied into the snap and started as services 43 | * The snap - respectively the executables - uses the content interface of the `ros-base` snap (here the ROS 2 runtime is provided). 44 | 45 | ### Build the Snap 46 | 47 | Start this script: 48 | 49 | ./build-snap-amd64.sh 50 | 51 | ## About 52 | 53 | SPDX-FileCopyrightText: Copyright (c) 2023 Bosch Rexroth AG 54 | 55 | 56 | 57 | ## Licenses 58 | 59 | SPDX-License-Identifier: Apache-2.0 -------------------------------------------------------------------------------- /simple-listener-dl-py/README.md: -------------------------------------------------------------------------------- 1 | # ROS 2 Listener that Writes a ctrlX Data Layer Value (Python) 2 | 3 | ## Introduction 4 | 5 | This project implements a ROS 2 listener, which receives a ROS 2 message and writes the value into a ctrlX Data Layer node. 6 | 7 | [Writing a simple publisher and subscriber (Python)](https://docs.ros.org/en/humble/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Py-Publisher-And-Subscriber.html#writing-a-simple-publisher-and-subscriber-python) was used as template. 8 | 9 | See also: 10 | 11 | * [Canonical Snapcraft - Deploying robotics applications](https://snapcraft.io/docs/robotics) 12 | * [Canonical - How to build a snap using ROS 2 Humble](https://canonical.com/blog/how-to-build-a-snap-using-ros-2-humble) 13 | 14 | ## Implementation 15 | 16 | * The directory structure is according colcon packages. 17 | * In `setup.py` and `setup.cfg` the [colcon](https://colcon.readthedocs.io/en/released/) package is defined. 18 | * `src/talker/talker/main.py` provides the main function 19 | * `src/talker/ros2/datalayer_reader_ros2_publisher.py` reads a ctrlX Data Layer values, creates a ROS 2 message and publishes it under the topic `ctrlXCpuUtilisationPercent`. 20 | * `src/talker/ctrlx_datalayer/ctrlx_datalayer_helper.py` contains helper functions regarding ctrlX Data Layer 21 | * `snap/snapcraft.yaml` defines which files are packed into the snap. 22 | 23 | ## Build process 24 | 25 | To build a snap run 26 | 27 | ./build-snap-amd64.sh 28 | 29 | The script contains following build steps: 30 | 31 | 1. Build the colcon package: 32 | 33 | colcon build 34 | 35 | 2. Clean the snapcraft helper directories: 36 | 37 | snapcraft clean --destructive-mode 38 | 39 | 3. Update helper directories and build the snap: 40 | 41 | snapcraft --destructive-mode 42 | 43 | Hint: Arm64-cross-build is not supported. 44 | 45 | ## Installation and test 46 | 47 | The `ros2-base` snap must already be installed. 48 | 49 | Install the created snap on a ctrlX OS. 50 | 51 | It publishes at the ROS 2 topic `MinimalPublisher`. 52 | 53 | The output can be checked with: 54 | 55 | sudo snap logs -f ros2-simple-talker 56 | 57 | ## About 58 | 59 | SPDX-FileCopyrightText: Copyright (c) 2023 Bosch Rexroth AG 60 | 61 | 62 | 63 | ## Licenses 64 | 65 | SPDX-License-Identifier: Apache-2.0 66 | -------------------------------------------------------------------------------- /simple-listener-dl-cpp/README.md: -------------------------------------------------------------------------------- 1 | # Simple ROS 2 Subscriber in C++ 2 | 3 | A simple ROS 2 node which subscribes to ROS messages of the topic `ros2_simple_talker_cpp` and publishes the value to the ctrlX Data Layer at the address `ros/listenercpp/mymessage`. From there the value can be used in any ctrlX App. 4 | 5 | ## Prerequisites 6 | 7 | * `ros-base` snap. The base snap which provides the ROS 2 runtime binaries. Has to be installed on ctrlX OS. See [ROS 2 Humble Base Snap](../ros2-base-humble-deb/README.md). 8 | * An Ubuntu based build environment to build an app. See [ctrlX Automation SDK](https://github.com/boschrexroth/ctrlx-automation-sdk). 9 | 10 | ## Basis for this Project 11 | 12 | This project is based on the official ROS 2 Tutorial: [Writing a simple publisher and subscriber (C++)](https://docs.ros.org/en/humble/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Cpp-Publisher-And-Subscriber.html#writing-a-simple-publisher-and-subscriber-c). 13 | 14 | ## Building a Snap 15 | 16 | Building a snap has two steps: 17 | 18 | 1. Colcon build: `CMakeLists.txt` defines how compile and link the C++ sources. 19 | 2. snap build: `snap/snapcraft.yaml` defines how the compiled binaries are packed into the snap and how they are called on ctrlX OS. 20 | 21 | ### Colcon Configuration 22 | 23 | The colcon build tool is configured by `CMakeLists.txt`. 24 | 25 | This section defines the ROS 2 packages needed: 26 | 27 | find_package(ament_cmake REQUIRED) 28 | find_package(rclcpp REQUIRED) 29 | find_package(std_msgs REQUIRED) 30 | 31 | And here the executables and their dependencies are defined: 32 | 33 | add_executable(listener src/subscriber_member_function.cpp) 34 | ament_target_dependencies(listener rclcpp std_msgs) 35 | 36 | ### Snapcraft Configuration 37 | 38 | `snap/snapcraft.yaml` defines how the snap will be build: 39 | 40 | * `install/` is dumped into the snap 41 | * also `wrapper/` 42 | * Two apps (talker and listener) are copied into the snap and started as services 43 | * The snap - respectively the executables - uses the content interface of the `ros-base` snap (here the ROS 2 runtime is provided). 44 | 45 | ### Build the Snap 46 | 47 | Start this script: 48 | 49 | ./build-snap-amd64.sh 50 | 51 | ## About 52 | 53 | SPDX-FileCopyrightText: Copyright (c) 2023 Bosch Rexroth AG 54 | 55 | 56 | 57 | ## Licenses 58 | 59 | SPDX-License-Identifier: Apache-2.0 -------------------------------------------------------------------------------- /simple-talker-dl-py/README.md: -------------------------------------------------------------------------------- 1 | # ROS 2 Talker of a ctrlX Data Layer Value (Python) 2 | 3 | ## Introduction 4 | 5 | This project implements a ROS 2 talker, which reads a ctrlX Data Layer value and publishes it as ROS 2 message. 6 | 7 | [Writing a simple publisher and subscriber (Python)](https://docs.ros.org/en/humble/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Py-Publisher-And-Subscriber.html#writing-a-simple-publisher-and-subscriber-python) was used as template. 8 | 9 | See also: 10 | 11 | * [Canonical Snapcraft - Deploying robotics applications](https://snapcraft.io/docs/robotics) 12 | * [Canonical - How to build a snap using ROS 2 Humble](https://canonical.com/blog/how-to-build-a-snap-using-ros-2-humble) 13 | 14 | ## Implementation 15 | 16 | * The directory structure is according colcon packages. 17 | * In `setup.py` and `setup.cfg` the [colcon](https://colcon.readthedocs.io/en/released/) package is defined. 18 | * `src/talker/talker/main.py` provides the main function 19 | * `src/talker/ros2/datalayer_reader_ros2_publisher.py` reads a ctrlX Data Layer value, creates a ROS 2 message and publishes it under the topic `ctrlXCpuUtilisationPercent`. 20 | * `src/talker/ctrlx_datalayer/ctrlx_datalayer_helper.py` contains helper functions regarding ctrlX Data Layer 21 | * `snap/snapcraft.yaml` defines which files are packed into the snap. 22 | 23 | ## Build process 24 | 25 | To build a snap run 26 | 27 | ./build-snap-amd64.sh 28 | 29 | The script contains following build steps: 30 | 31 | 1. Build the colcon package: 32 | 33 | colcon build 34 | 35 | 2. Clean the snapcraft helper directories: 36 | 37 | snapcraft clean --destructive-mode 38 | 39 | 3. Update helper directories and build the snap: 40 | 41 | snapcraft --destructive-mode 42 | 43 | Hint: Arm64-cross-build is not supported. 44 | 45 | ## Installation and test 46 | 47 | The `ros2-base` snap must already be installed. 48 | 49 | Install the created snap on ctrlX OS. 50 | 51 | It publishes at the ROS 2 topic `MinimalPublisher`. 52 | 53 | The output can be checked with: 54 | 55 | sudo snap logs -f ros2-simple-talker 56 | 57 | ## Build, install and test 58 | 59 | With following command you can combine the build, installation and test steps - here the target is a ctrlX COREvirtual with port forwarding. 60 | 61 | ../../../public/scripts/build-upload-log-snap.sh -PF 62 | 63 | ## About 64 | 65 | SPDX-FileCopyrightText: Copyright (c) 2023 Bosch Rexroth AG 66 | 67 | 68 | 69 | ## Licenses 70 | 71 | SPDX-License-Identifier: Apache-2.0 72 | -------------------------------------------------------------------------------- /simple-talker-py/README.md: -------------------------------------------------------------------------------- 1 | # ROS 2 Simple Talker (Python) 2 | 3 | ## Introduction 4 | 5 | This project implements a simple ROS 2 talker, derived from [Writing a simple publisher and subscriber (Python)](https://docs.ros.org/en/humble/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Py-Publisher-And-Subscriber.html#writing-a-simple-publisher-and-subscriber-python). 6 | 7 | The differences to this template project are: 8 | 9 | * ROS 2 runtime functions are provided by the `ros2-base` snap, which must be preinstalled on the ctrlX. 10 | * The project files are packed into a snap. 11 | 12 | See also: 13 | 14 | * [Canonical Snapcraft - Deploying robotics applications](https://snapcraft.io/docs/robotics) 15 | * [Canonical - How to build a snap using ROS 2 Humble](https://canonical.com/blog/how-to-build-a-snap-using-ros-2-humble) 16 | 17 | ## Implementation 18 | 19 | * The directory structure is according colcon packages. 20 | * In `setup.py` and `setup.cfg` the [colcon](https://colcon.readthedocs.io/en/released/) package is defined. 21 | * The one and only Python script is `main_minimal_subscriber.py`, stored in the directory `src/listener/listener/` 22 | * It contains the main function and a class `MinimalSubscriber`, derived from `rclpy.node.Node` 23 | * `snap/snapcraft.yaml` defines which files are packed into the snap. 24 | 25 | ## Build Process 26 | 27 | To build a snap run 28 | 29 | ./build-snap-amd64.sh 30 | 31 | The script contains following build steps: 32 | 33 | 1. Build the colcon package: 34 | 35 | colcon build 36 | 37 | 2. Clean the snapcraft helper directories: 38 | 39 | snapcraft clean --destructive-mode 40 | 41 | 3. Update helper directories and build the snap: 42 | 43 | snapcraft --destructive-mode 44 | 45 | Hint: To keep the project simple the arm64-cross-build is not supported. 46 | 47 | ## Installation and Test 48 | 49 | The `ros2-base` snaps must already be installed. 50 | 51 | Install the created snap on ctrlX OS. 52 | 53 | It publishes at the ROS 2 topic `MinimalPublisher`. 54 | 55 | The output can be checked with: 56 | 57 | sudo snap logs -f ros2-simple-talker 58 | 59 | ## Build, install and test 60 | 61 | With following command you can combine the build, installation and test steps - here the target is a ctrlX COREvirtual with port forwarding. 62 | 63 | ../../../public/scripts/build-upload-log-snap.sh -PF 64 | 65 | ## About 66 | 67 | SPDX-FileCopyrightText: Copyright (c) 2024 Bosch Rexroth AG 68 | 69 | 70 | 71 | ## Licenses 72 | 73 | SPDX-License-Identifier: MIT 74 | -------------------------------------------------------------------------------- /ros2-base-humble-deb/README.md: -------------------------------------------------------------------------------- 1 | # ROS 2 Humble on ctrlX OS: A Snap Implementation of the ROS 2 Humble Distribution using ROS 2 Debian Package 2 | 3 | ## Introduction 4 | 5 | We recommend for ROS 2 applications running on a ctrlX OS this approach: 6 | 7 | * Build and install a __base snap__ containing the ROS 2 runtime and the components used for the ctrlX Data Layer access. 8 | * This base snap provides its components using the snap [content interface](https://snapcraft.io/docs/content-interface). 9 | * Pack your ROS 2 application into one or more overlay snaps. 10 | * Let these overlay snap use the ROS 2 runtime and the ctrlX Data Layer via the content interface of the __base snap__. 11 | 12 | This documentation describes how the base snap `ros2-base` can be build. 13 | 14 | !!! important 15 | The build for arm64 devices uses Docker and is in an unreleased state! 16 | 17 | ## Content of the Base Snap 18 | 19 | The file `snap/snapcraft.yaml` defines how the base snap will be build. 20 | 21 | ### Debian Packages 22 | 23 | The snapcraft plugin [colcon](https://snapcraft.io/docs/colcon-plugin) is used to download Debian packages: 24 | 25 | * Needed during build process: make, gcc, g++ 26 | * Needed at runtime: software-properties-common, ros-humble-ros-base, python3-argcomplete, ca-certificates, ctrlx-datalayer 27 | 28 | ### Python Wheels 29 | 30 | The snapcraft plugin [python](https://snapcraft.io/docs/python-plugin) is used to download python wheels: 31 | 32 | * python3-wheel 33 | * ctrlx-datalayer 34 | * empy 35 | * numpy 36 | * rosdep 37 | * rosdistro 38 | * colcon-core 39 | * lark rosdep 40 | * rosdistro 41 | * colcon-core 42 | * lark 43 | 44 | ### Content Interface 45 | 46 | The base snap makes its files available via the content interface `executables`. 47 | 48 | ## Building the Base Snap 49 | 50 | ### AMD64 51 | 52 | Compiling for AMD64 on an AMD64 machine is straight-forward. Apart from the `snap/snapcraft.yaml` file and a shell script that calls snapcraft, nothing else is needed here. 53 | 54 | Call: 55 | 56 | ./build-snap-amd64.sh 57 | 58 | ### ARM64 59 | 60 | We recommend using a native ARM64 host environment to compile the ARM64 code. Set up a corresponding hardware, for example __Raspberry Pi__ or a virtual environment, for example __Qemu__ [installation scripts](https://github.com/boschrexroth/ctrlx-automation-sdk/tree/main/scripts/environment). 61 | 62 | ## About 63 | 64 | SPDX-FileCopyrightText: Copyright (c) 2023-2025 Bosch Rexroth AG 65 | 66 | 67 | 68 | ## Licenses 69 | 70 | SPDX-License-Identifier: MIT 71 | -------------------------------------------------------------------------------- /simple-listener-py/README.md: -------------------------------------------------------------------------------- 1 | # ROS 2 Simple Listener (Python) 2 | 3 | ## Introduction 4 | 5 | This project implements a simple ROS 2 listener, derived from [Writing a simple publisher and subscriber (Python)](https://docs.ros.org/en/humble/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Py-Publisher-And-Subscriber.html#writing-a-simple-publisher-and-subscriber-python). 6 | 7 | The differences to this template project are: 8 | 9 | * ROS 2 runtime functions are provided by the `ros2-base` snap, which must be preinstalled on the ctrlX. 10 | * The project files are packed into a snap. 11 | 12 | See also: 13 | 14 | * [Canonical Snapcraft - Deploying robotics applications](https://snapcraft.io/docs/robotics) 15 | * [Canonical - How to build a snap using ROS 2 Humble](https://canonical.com/blog/how-to-build-a-snap-using-ros-2-humble) 16 | 17 | ## Implementation 18 | 19 | * The directory structure is according colcon packages. 20 | * In `setup.py` and `setup.cfg` the [colcon](https://colcon.readthedocs.io/en/released/) package is defined. 21 | * The one and only Python script is `main_minimal_subscriber.py`, stored in the directory `src/listener/listener/` 22 | * It contains the main function and a class `MinimalSubscriber`, derived from `rclpy.node.Node` 23 | * `snap/snapcraft.yaml` defines which files are packed into the snap. 24 | 25 | ## Build Process 26 | 27 | To build a snap run 28 | 29 | ./build-snap-amd64.sh 30 | 31 | The script contains following build steps: 32 | 33 | 1. Build the colcon package: 34 | 35 | colcon build 36 | 37 | 2. Clean the snapcraft helper directories: 38 | 39 | snapcraft clean --destructive-mode 40 | 41 | 3. Update helper directories and build the snap: 42 | 43 | snapcraft --destructive-mode 44 | 45 | Hint: To keep the project simple the arm64-cross-build is not supported. 46 | 47 | ## Installation and Test 48 | 49 | Following snaps must already be installed: 50 | 51 | * `ros2-base` 52 | * `ros2-simple-talker` 53 | 54 | Install the created snap on a ctrlX OS. 55 | 56 | It listens at the ROS 2 topic `MinimalPublisher`. 57 | 58 | The output can be checked with: 59 | 60 | sudo snap logs -f ros2-simple-listener 61 | 62 | ## Build, install and test 63 | 64 | With following command you can combine the build, installation and test steps - here the target is a ctrlX COREvirtual with port forwarding. 65 | 66 | ../../../public/scripts/build-upload-log-snap.sh -PF 67 | 68 | ## About 69 | 70 | SPDX-FileCopyrightText: Copyright (c) 2023 Bosch Rexroth AG 71 | 72 | 73 | 74 | ## Licenses 75 | 76 | SPDX-License-Identifier: Apache-2.0 77 | 78 | -------------------------------------------------------------------------------- /simple-listener-dl-cpp/src/app/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.8) 2 | project(app) 3 | set(TARGET_PROJECT_NAME listener) 4 | 5 | if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") 6 | add_compile_options(-Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-unused-function) 7 | endif() 8 | 9 | ############################################################################### 10 | # SHM as Default transport 11 | ############################################################################### 12 | option(SHM_TRANSPORT_DEFAULT "Add SHM transport to the default transports" OFF) # -> "Permission denied -> Function compute_per_allocation_extra_size" 13 | 14 | # find dependencies 15 | find_package(ament_cmake REQUIRED) 16 | find_package(rclcpp REQUIRED) 17 | find_package(std_msgs REQUIRED) 18 | 19 | 20 | # 21 | # Set link directories 22 | # 23 | MESSAGE( STATUS "Libraries directory: ${LIBRARY_DIR}") 24 | link_directories( 25 | ${LIBRARY_DIR} 26 | ${LIBRARY_DEP_DIR} 27 | ) 28 | 29 | # User dependency directory 30 | # 31 | set (USER_DEPENDENCY_DIR ${CMAKE_CURRENT_LIST_DIR}/../../../..) 32 | 33 | SET ( PRIVATE_INCLUDE_DIRS 34 | ${CMAKE_CURRENT_LIST_DIR} 35 | ${CMAKE_CURRENT_BINARY_DIR} 36 | ${CMAKE_CURRENT_LIST_DIR}/include 37 | ${USER_DEPENDENCY_DIR}/include 38 | ${USER_DEPENDENCY_DIR}/include/comm.datalayer 39 | ) 40 | 41 | # Set target link libraries 42 | 43 | 44 | if(BUILD_TESTING) 45 | find_package(ament_lint_auto REQUIRED) 46 | # the following line skips the linter which checks for copyrights 47 | # comment the line when a copyright and license is added to all source files 48 | set(ament_cmake_copyright_FOUND TRUE) 49 | # the following line skips cpplint (only works in a git repo) 50 | # comment the line when this package is in a git repo and when 51 | # a copyright and license is added to all source files 52 | set(ament_cmake_cpplint_FOUND TRUE) 53 | ament_lint_auto_find_test_dependencies() 54 | endif() 55 | 56 | add_executable(listener src/subscriber_member_function.cpp) 57 | ament_target_dependencies(listener rclcpp std_msgs) 58 | 59 | 60 | # 61 | # Set target include directories 62 | # 63 | target_include_directories ( ${TARGET_PROJECT_NAME} 64 | PUBLIC ${PUBLIC_INCLUDE_DIRS} 65 | PUBLIC ${LIBRARY_INCLUDES} 66 | PRIVATE ${PRIVATE_INCLUDE_DIRS} 67 | ) 68 | # 69 | target_link_libraries(${TARGET_PROJECT_NAME} -Wl,--no-undefined) 70 | target_link_libraries(${TARGET_PROJECT_NAME} 71 | libcomm_datalayer.so 72 | pthread 73 | # systemd 74 | # zmq 75 | ssl 76 | crypto 77 | ) 78 | 79 | install(TARGETS 80 | listener 81 | DESTINATION lib/${PROJECT_NAME}) 82 | 83 | ament_package() 84 | -------------------------------------------------------------------------------- /simple-talker-dl-cpp/README.md: -------------------------------------------------------------------------------- 1 | # Simple ROS 2 Subscriber in C++ 2 | 3 | A simple ROS 2 node which cyclically reads the CPU usage from the ctrlX Data Layer by reading the address `framework/metrics/system/cpu-utilisation-percent` and pushes on the ROS2 topic `ros2_simple_talker_cpp`. 4 | In the ctrlX Data Layer you can find any kind of information about the device, process, fieldbus and periphery. 5 | Please note, that this is a very basic example which uses the simplest method of reading in the ctrlX Data Layer. For improved performance and scalability you should consider creating a subscription instead of performing synchronuous (blocking) reads. 6 | 7 | ## Prerequisites 8 | 9 | * `ros-base` snap. The base snap which provides the ROS 2 runtime binaries. Has to be installed on ctrlX OS. See [ROS 2 Humble Base Snap](../ros2-base-humble-deb/README.md). 10 | * An Ubuntu based build environment to build an app. See [ctrlX Automation SDK](https://github.com/boschrexroth/ctrlx-automation-sdk). 11 | 12 | ## Basis for this Project 13 | 14 | This project is based on the official ROS 2 Tutorial: [Writing a simple publisher and subscriber (C++)](https://docs.ros.org/en/humble/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Cpp-Publisher-And-Subscriber.html#writing-a-simple-publisher-and-subscriber-c). 15 | 16 | ## Building a Snap 17 | 18 | Building a snap has two steps: 19 | 20 | 1. Colcon build: `CMakeLists.txt` defines how compile and link the C++ sources. 21 | 2. snap build: `snap/snapcraft.yaml` defines how the compiled binaries are packed into the snap and how they are called on ctrlX OS. 22 | 23 | ### Colcon Configuration 24 | 25 | The colcon build tool is configured by `CMakeLists.txt`. 26 | 27 | This section defines the ROS 2 packages needed: 28 | 29 | find_package(ament_cmake REQUIRED) 30 | find_package(rclcpp REQUIRED) 31 | find_package(std_msgs REQUIRED) 32 | 33 | And here the executables and their dependencies are defined: 34 | 35 | add_executable(listener src/subscriber_member_function.cpp) 36 | ament_target_dependencies(listener rclcpp std_msgs) 37 | 38 | ### Snapcraft Configuration 39 | 40 | `snap/snapcraft.yaml` defines how the snap will be build: 41 | 42 | * `install/` is dumped into the snap 43 | * also `wrapper/` 44 | * Two apps (talker and listener) are copied into the snap and started as services 45 | * The snap - respectively the executables - uses the content interface of the `ros-base` snap (here the ROS 2 runtime is provided). 46 | 47 | ### Build the Snap 48 | 49 | Start this script: 50 | 51 | ./build-snap-amd64.sh 52 | 53 | ## About 54 | 55 | SPDX-FileCopyrightText: Copyright (c) 2023 Bosch Rexroth AG 56 | 57 | 58 | 59 | ## Licenses 60 | 61 | SPDX-License-Identifier: Apache-2.0 -------------------------------------------------------------------------------- /simple-listener-dl-py/src/app/ctrlx_datalayer/ctrlx_provider_node.py: -------------------------------------------------------------------------------- 1 | """Provides a ctrlX Data Layer node to store the received ROS 2 value.""" 2 | 3 | # SPDX-FileCopyrightText: Bosch Rexroth AG 4 | # 5 | # SPDX-License-Identifier: MIT 6 | 7 | import ctrlxdatalayer 8 | from ctrlxdatalayer.provider import Provider 9 | from ctrlxdatalayer.provider_node import ProviderNode, ProviderNodeCallbacks, NodeCallback 10 | from ctrlxdatalayer.variant import Result, Variant 11 | 12 | 13 | class CtrlXProviderNode: 14 | """ 15 | Class CtrlXProviderNode. 16 | 17 | Provides a ctrlX Data Layer node and handles all events via callback functions. 18 | """ 19 | 20 | def __init__(self, 21 | datalayer_provider: Provider, 22 | address: str, 23 | variant: Variant): 24 | """Initialize the instance.""" 25 | self.cbs = ProviderNodeCallbacks( 26 | self.__on_create, 27 | self.__on_remove, 28 | self.__on_browse, 29 | self.__on_read, 30 | self.__on_write, 31 | self.__on_metadata 32 | ) 33 | 34 | self.providerNode = ProviderNode(self.cbs) 35 | 36 | self.provider = datalayer_provider 37 | self.address = address 38 | self.variant = variant 39 | 40 | def register_node(self): 41 | """Register the node.""" 42 | return self.provider.register_node(self.address, self.providerNode) 43 | 44 | def unregister_node(self): 45 | """Unregister the node.""" 46 | self.provider.unregister_node(self.address) 47 | 48 | def set_value(self, value: Variant): 49 | """Set the value.""" 50 | self.variant = value 51 | 52 | def __on_create(self, userdata: ctrlxdatalayer.clib.userData_c_void_p, 53 | address: str, data: Variant, cb: NodeCallback): 54 | """Handle on_create event.""" 55 | print('__on_create()', 'address:', address, 'userdata:', userdata) 56 | cb(Result.OK, data) 57 | 58 | def __on_remove(self, userdata: ctrlxdatalayer.clib.userData_c_void_p, 59 | address: str, cb: NodeCallback): 60 | """Handle on_remove event.""" 61 | print('__on_remove()', 'address:', address, 'userdata:', userdata) 62 | cb(Result.UNSUPPORTED, None) 63 | 64 | def __on_browse(self, 65 | userdata: ctrlxdatalayer.clib.userData_c_void_p, 66 | address: str, 67 | cb: NodeCallback): 68 | """Handle on_browse event.""" 69 | variant = Variant() 70 | variant.set_array_string([]) 71 | cb(Result.OK, variant) 72 | 73 | def __on_read(self, userdata: ctrlxdatalayer.clib.userData_c_void_p, 74 | address: str, data: Variant, cb: NodeCallback): 75 | """Handle on_read event.""" 76 | variant = self.variant 77 | cb(Result.OK, variant) 78 | 79 | def __on_write(self, userdata: ctrlxdatalayer.clib.userData_c_void_p, 80 | address: str, data: Variant, cb: NodeCallback): 81 | """Handle on_write event.""" 82 | cb(Result.UNSUPPORTED, None) 83 | 84 | def __on_metadata(self, userdata: ctrlxdatalayer.clib.userData_c_void_p, 85 | address: str, 86 | cb: NodeCallback): 87 | """Handle on_metadata event.""" 88 | cb(Result.FAILED, None) 89 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | Please follow the Code of Conduct in all interactions with this project. 4 | 5 | ## Our Pledge 6 | 7 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 8 | 9 | ## Our Standards 10 | 11 | Examples of behavior that contributes to creating a positive environment include: 12 | 13 | * Using welcoming and inclusive language 14 | * Being respectful of differing viewpoints and experiences 15 | * Gracefully accepting constructive criticism 16 | * Focusing on what is best for the community 17 | * Showing empathy towards other community members 18 | 19 | Examples of unacceptable behavior by participants include: 20 | 21 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 22 | * Trolling, insulting/derogatory comments, and personal or political attacks 23 | * Public or private harassment 24 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 25 | * Other conduct which could reasonably be considered inappropriate in a professional setting 26 | 27 | ## Our Responsibilities 28 | 29 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 30 | 31 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 32 | 33 | ## Scope 34 | 35 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 36 | 37 | ## Enforcement 38 | 39 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at . All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 40 | 41 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 42 | 43 | ## Attribution 44 | 45 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 46 | 47 | [homepage]: http://contributor-covenant.org 48 | [version]: http://contributor-covenant.org/version/1/4/ 49 | -------------------------------------------------------------------------------- /simple-listener-dl-py/src/app/ros2/ros2_listener_ctrlx_provider.py: -------------------------------------------------------------------------------- 1 | """Listens for ROS 2 messages and stores them into the ctrlX Data Layer.""" 2 | 3 | # SPDX-FileCopyrightText: Bosch Rexroth AG 4 | # 5 | # SPDX-License-Identifier: MIT 6 | 7 | import rclpy 8 | from rclpy.node import Node 9 | 10 | import std_msgs.msg 11 | 12 | import ctrlxdatalayer 13 | from ctrlxdatalayer.variant import Result, Variant 14 | 15 | from ctrlx_datalayer.ctrlx_datalayer_helper import get_provider 16 | from ctrlx_datalayer.ctrlx_provider_node import CtrlXProviderNode 17 | 18 | 19 | class Ros2ListenerDataLayerProvider(Node): 20 | """ 21 | Class Ros2ListenerDataLayerProvider. 22 | 23 | Receives ROS 2 messages and stores the received values into a ctrlX Data Layer node. 24 | """ 25 | 26 | def __init__(self, dl_address, ros2_topic): 27 | """Initialize the instance.""" 28 | self.dl_address = dl_address 29 | self.ros2_topic = ros2_topic 30 | 31 | self.datalayer_system = None 32 | self.datalayer_provider = None 33 | self.variant = Variant() 34 | self.provider_node = None 35 | 36 | self.ros2_subscription = None 37 | self.ros2_msg_data = None 38 | 39 | def read_data_layer_value(self): 40 | """Read the value from the ctrlX Data Layer.""" 41 | print('INFO Reading ctrlX Data Layer node', self.dl_address, ' - BEGIN') 42 | result, variant = self.datalayer_provider.read_sync(self.dl_address) 43 | print('INFO Reading ctrlX Data Layer node', self.dl_address, ' - END') 44 | if result != Result.OK: 45 | print('ERROR Reading ctrlX Data Layer node', self.dl_address, 'failed', result) 46 | return None 47 | 48 | print('INFO Data type ', variant.get_type().name) 49 | return variant 50 | 51 | def start(self): 52 | """Start the activity.""" 53 | self.datalayer_system = ctrlxdatalayer.system.System('') 54 | self.datalayer_system.start(False) 55 | 56 | print('INFO Creating ctrlX Data Layer connnection') 57 | self.datalayer_provider, connection_string = get_provider(self.datalayer_system) 58 | if self.datalayer_provider is None: 59 | print('ERROR Creating ctrlX Data Layer connnection to', connection_string, 'failed') 60 | return False 61 | self.datalayer_provider.start() 62 | 63 | self.variant.set_float64(-1.0) 64 | self.provider_node = CtrlXProviderNode(self.datalayer_provider, self.dl_address, self.variant) 65 | result = self.provider_node.register_node() 66 | if result != Result.OK: 67 | print('ERROR Registering', self.dl_address, 'failed') 68 | return False 69 | 70 | print('INFO Initializing ROS 2 node Ros2ListenerCtrlxProvider') 71 | super().__init__('Ros2ListenerCtrlxProvider') 72 | 73 | print('INFO Creating ROS 2 listener to topic', self.ros2_topic) 74 | self.ros2_subscription = self.create_subscription(std_msgs.msg.Float64, self.ros2_topic, self.listener_callback, 10) 75 | if self.ros2_subscription is None: 76 | print('ERROR Creating ROS 2 subscription failed') 77 | return False 78 | 79 | return True 80 | 81 | def listener_callback(self, msg): 82 | """Get the ROS 2 message data and store it into ctrlX Data Layer.""" 83 | self.get_logger().info('Received "%s"' % msg.data) 84 | self.ros2_msg_data = msg.data 85 | self.variant.set_float64(msg.data) 86 | self.provider_node.set_value(self.variant) 87 | 88 | def stop(self): 89 | """Stop the activity.""" 90 | self.datalayer_system = ctrlxdatalayer.system.System('') 91 | self.datalayer_system.stop(False) 92 | 93 | if self.timer is not None: 94 | self.destroy_timer(self.timer) 95 | -------------------------------------------------------------------------------- /simple-talker-dl-py/src/app/ctrlx_datalayer/ctrlx_datalayer_helper.py: -------------------------------------------------------------------------------- 1 | """ 2 | Helper script to connect to ctrlX Data Layer. 3 | 4 | This script provides auxiliary methods to create ctrlX Datalayer client and 5 | provider connections to ctrlX CORE devices. 6 | 7 | It can be used for both running in an app build environment (QEMU VM) and 8 | within the snap environment on the ctrlX CORE. 9 | 10 | Feel free to use it in your projects and to change it if necessary. 11 | 12 | For ease of use, the default values for IP address, user, password and SSL 13 | port are chosen to match the settings of a newly created ctrlX CORE device: 14 | 15 | ip='192.168.1.1' 16 | user='boschrexroth' 17 | password='boschrexroth' 18 | ssl_port=443 19 | 20 | If these values do not suit your use case, explicitly pass the parameters that 21 | require different values. 22 | 23 | Here some examples: 24 | 25 | 1. ctrlX CORE or ctrlX COREvirtual with another IP address, user and password: 26 | 27 | client, client_connection = get_client(system, ip='192.168.1.100', 28 | user='admin', password='-$_U/{X$aG}Z3/e<') 29 | 30 | 2. ctrlX COREvirtual with port forwarding running on the same host as the app 31 | build environment (QEMU VM): 32 | 33 | client, client_connection = 34 | get_client(system, ip='10.0.2.2', ssl_port=8443) 35 | 36 | Remarks: 37 | 10.0.2.2 is the IP address of the host from the point of view of the app 38 | build environment (QEMU VM). 39 | 8443 is the host port which is forwarded to the SSL port (=433) of the 40 | ctrlX COREvirtual 41 | 42 | 43 | IMPORTANT: 44 | You need not change the parameter settings before building a snap and 45 | installing the snap on a ctrlX CORE. 46 | The method get_connection_string detects the snap environment and uses 47 | automatically inter process communication. 48 | 49 | Therefor the connection string to the ctrlX Datalayer is: 50 | 51 | 'ipc://' 52 | 53 | """ 54 | 55 | # SPDX-FileCopyrightText: Bosch Rexroth AG 56 | # 57 | # SPDX-License-Identifier: MIT 58 | 59 | import os 60 | 61 | import ctrlxdatalayer 62 | 63 | 64 | def get_connection_string( 65 | ip='192.168.1.1', 66 | user='boschrexroth', 67 | password='boschrexroth', 68 | ssl_port=443): 69 | """ 70 | Combine a ctrlX Datalayer connection string. 71 | 72 | @param[in] ip IP address of the ctrlX CORE. Use '10.0.2.2' to connect to a ctrlX COREvirtual with port forwarding. 73 | @param[in] user Name of the user. 74 | @param[in] password Password of the user. 75 | @param[in] ssl_port Port number for a SSL connection. ctrlX COREvirtual with port forwarding: Use the host port (default 8443) forwarded to port 22 of the ctrlX virtual. 76 | @returns connection_string The connection string: 'ipc://' for running in snap environment, 'tcp://...' for running in environment. 77 | """ 78 | if 'SNAP' in os.environ: 79 | return 'ipc://' 80 | 81 | # Client connection port 2069 resp. Provider connection port 2070 are obsolete 82 | connection_string = 'tcp://'+user+':'+password+'@'+ip 83 | 84 | if (ssl_port == 443): 85 | return connection_string 86 | 87 | return connection_string+'?sslport=' + str(ssl_port) 88 | 89 | 90 | def get_client(system: ctrlxdatalayer.system.System, 91 | ip='192.168.1.1', 92 | user='boschrexroth', 93 | password='boschrexroth', 94 | ssl_port=8443): 95 | """ 96 | Create a ctrlX Datalayer client instance. 97 | 98 | @param[in] system A ctrlxdatalayer.system.System instance 99 | @param[in] ip IP address of the ctrlX CORE. Use '10.0.2.2' to connect to a ctrlX COREvirtual with port forwarding. 100 | @param[in] user Name of the user. 101 | @param[in] password Password of the user. 102 | @param[in] ssl_port Port number for a SSL connection. ctrlX COREvirtual with port forwarding: Use the host port (default 8443) forwarded to port 22 of the ctrlX virtual. 103 | @returns tuple (client, connection_string) 104 | @return The ctrlxdatalayer.client.Client instance or None if failed 105 | @return The connection string or None if failed 106 | """ 107 | connection_string = get_connection_string( 108 | ip, user, password, ssl_port) 109 | client = system.factory().create_client(connection_string) 110 | if client.is_connected(): 111 | return client, connection_string 112 | client.close() 113 | 114 | return None, connection_string 115 | 116 | 117 | def get_provider(system: ctrlxdatalayer.system.System, 118 | ip='192.168.1.1', 119 | user='boschrexroth', 120 | password='boschrexroth', 121 | ssl_port=443): 122 | """ 123 | Create a ctrlX Datalayer provider instance. 124 | 125 | @param[in] system A ctrlxdatalayer.system.System instance 126 | @param[in] ip IP address of the ctrlX CORE. Use '10.0.2.2' to connect to a ctrlX COREvirtual with port forwarding. 127 | @param[in] user Name of the user. 128 | @param[in] password Password of the user. 129 | @param[in] ssl_port Port number for a SSL connection. ctrlX COREvirtual with port forwarding: Use the host port (default 8443) forwarded to port 22 of the ctrlX virtual. 130 | @returns tuple (provider, connection_string) 131 | @return , a ctrlxdatalayer.provider.Provider instance or None if failed, 132 | @return , a connection string or None if failed 133 | """ 134 | connection_string = get_connection_string( 135 | ip, user, password, ssl_port) 136 | provider = system.factory().create_provider(connection_string) 137 | if (provider.start() == ctrlxdatalayer.variant.Result.OK) & provider.is_connected(): 138 | return provider, connection_string 139 | provider.close() 140 | 141 | return None, connection_string 142 | -------------------------------------------------------------------------------- /simple-listener-dl-py/src/app/ctrlx_datalayer/ctrlx_datalayer_helper.py: -------------------------------------------------------------------------------- 1 | """ 2 | Helper script to connect to ctrlX Data Layer. 3 | 4 | This script provides auxiliary methods to create ctrlX Datalayer client and 5 | provider connections to ctrlX CORE devices. 6 | 7 | It can be used for both running in an app build environment (QEMU VM) and 8 | within the snap environment on the ctrlX CORE. 9 | 10 | Feel free to use it in your projects and to change it if necessary. 11 | 12 | For ease of use, the default values for IP address, user, password and SSL 13 | port are chosen to match the settings of a newly created ctrlX CORE device: 14 | 15 | ip='192.168.1.1' 16 | user='boschrexroth' 17 | password='boschrexroth' 18 | ssl_port=443 19 | 20 | If these values do not suit your use case, explicitly pass the parameters that 21 | require different values. 22 | 23 | Here some examples: 24 | 25 | 1. ctrlX CORE or ctrlX COREvirtual with another IP address, user and password: 26 | 27 | client, client_connection = get_client(system, ip='192.168.1.100', 28 | user='admin', password='-$_U/{X$aG}Z3/e<') 29 | 30 | 2. ctrlX COREvirtual with port forwarding running on the same host as the app 31 | build environment (QEMU VM): 32 | 33 | client, client_connection = 34 | get_client(system, ip='10.0.2.2', ssl_port=8443) 35 | 36 | Remarks: 37 | 10.0.2.2 is the IP address of the host from the point of view of the app 38 | build environment (QEMU VM). 39 | 8443 is the host port which is forwarded to the SSL port (=433) of the 40 | ctrlX COREvirtual 41 | 42 | 43 | IMPORTANT: 44 | You need not change the parameter settings before building a snap and 45 | installing the snap on a ctrlX CORE. 46 | The method get_connection_string detects the snap environment and uses 47 | automatically inter process communication. 48 | 49 | Therefor the connection string to the ctrlX Datalayer is: 50 | 51 | 'ipc://' 52 | 53 | """ 54 | 55 | # SPDX-FileCopyrightText: Bosch Rexroth AG 56 | # 57 | # SPDX-License-Identifier: MIT 58 | 59 | import os 60 | 61 | import ctrlxdatalayer 62 | 63 | 64 | def get_connection_string( 65 | ip='192.168.1.1', 66 | user='boschrexroth', 67 | password='boschrexroth', 68 | ssl_port=443): 69 | """ 70 | Combine a ctrlX Datalayer connection string. 71 | 72 | @param[in] ip IP address of the ctrlX CORE. Use '10.0.2.2' to connect to a ctrlX COREvirtual with port forwarding. 73 | @param[in] user Name of the user. 74 | @param[in] password Password of the user. 75 | @param[in] ssl_port Port number for a SSL connection. ctrlX COREvirtual with port forwarding: Use the host port (default 8443) forwarded to port 22 of the ctrlX virtual. 76 | @returns connection_string The connection string: 'ipc://' for running in snap environment, 'tcp://...' for running in environment. 77 | """ 78 | if 'SNAP' in os.environ: 79 | return 'ipc://' 80 | 81 | # Client connection port 2069 resp. Provider connection port 2070 are obsolete 82 | connection_string = 'tcp://'+user+':'+password+'@'+ip 83 | 84 | if (ssl_port == 443): 85 | return connection_string 86 | 87 | return connection_string+'?sslport=' + str(ssl_port) 88 | 89 | 90 | def get_client(system: ctrlxdatalayer.system.System, 91 | ip='192.168.1.1', 92 | user='boschrexroth', 93 | password='boschrexroth', 94 | ssl_port=8443): 95 | """ 96 | Create a ctrlX Datalayer client instance. 97 | 98 | @param[in] system A ctrlxdatalayer.system.System instance 99 | @param[in] ip IP address of the ctrlX CORE. Use '10.0.2.2' to connect to a ctrlX COREvirtual with port forwarding. 100 | @param[in] user Name of the user. 101 | @param[in] password Password of the user. 102 | @param[in] ssl_port Port number for a SSL connection. ctrlX COREvirtual with port forwarding: Use the host port (default 8443) forwarded to port 22 of the ctrlX virtual. 103 | @returns tuple (client, connection_string) 104 | @return The ctrlxdatalayer.client.Client instance or None if failed 105 | @return The connection string or None if failed 106 | """ 107 | connection_string = get_connection_string( 108 | ip, user, password, ssl_port) 109 | client = system.factory().create_client(connection_string) 110 | if client.is_connected(): 111 | return client, connection_string 112 | client.close() 113 | 114 | return None, connection_string 115 | 116 | 117 | def get_provider(system: ctrlxdatalayer.system.System, 118 | ip='192.168.1.1', 119 | user='boschrexroth', 120 | password='boschrexroth', 121 | ssl_port=443): 122 | """ 123 | Create a ctrlX Datalayer provider instance. 124 | 125 | @param[in] system A ctrlxdatalayer.system.System instance 126 | @param[in] ip IP address of the ctrlX CORE. Use '10.0.2.2' to connect to a ctrlX COREvirtual with port forwarding. 127 | @param[in] user Name of the user. 128 | @param[in] password Password of the user. 129 | @param[in] ssl_port Port number for a SSL connection. ctrlX COREvirtual with port forwarding: Use the host port (default 8443) forwarded to port 22 of the ctrlX virtual. 130 | @returns tuple (provider, connection_string) 131 | @return , a ctrlxdatalayer.provider.Provider instance or None if failed, 132 | @return , a connection string or None if failed 133 | """ 134 | connection_string = get_connection_string( 135 | ip, user, password, ssl_port) 136 | provider = system.factory().create_provider(connection_string) 137 | if (provider.start() == ctrlxdatalayer.variant.Result.OK) & provider.is_connected(): 138 | return provider, connection_string 139 | provider.close() 140 | 141 | return None, connection_string 142 | -------------------------------------------------------------------------------- /simple-listener-dl-cpp/src/app/src/ctrlx_datalayer_helper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Bosch Rexroth AG 3 | * 4 | * SPDX-License-Identifier: MIT 5 | */ 6 | 7 | #ifndef CTRLX_DATALAYER_HELPER_H 8 | #define CTRLX_DATALAYER_HELPER_H 9 | 10 | /*! \file 11 | * 12 | * This header file provides auxiliary methods to create ctrlX Datalayer client and provider connections to ctrlX CORE devices. 13 | * It can be used for both running in an app build environment (QEMU VM) and within the snap environment on the ctrlX CORE. 14 | * 15 | * Feel free to use it in your projects and to change it if necessary. 16 | * 17 | * For ease of use, the default values for IP address, user, password and SSL port are chosen to match the settings of a 18 | * newly created ctrlX CORE device: 19 | * 20 | * ip="192.168.1.1" 21 | * user="boschrexroth" 22 | * password="boschrexroth" 23 | * ssl_port=443 24 | * 25 | * If these values do not suit your use case, explicitly pass the parameters that require different values. 26 | * Here some examples: 27 | * 28 | * 1. ctrlX CORE or ctrlX COREvirtual with another IP address, user and password: 29 | * 30 | * client, client_connection = get_client(system, ip="192.168.1.100", user="admin", password="-$_U/{X$aG}Z3/e<") 31 | * 32 | * 2. ctrlX COREvirtual with port forwarding running on the same host as the app build environment (QEMU VM): 33 | * 34 | * client, client_connection = get_client(system, ip="10.0.2.2", ssl_port=8443) 35 | * 36 | * Remarks: 37 | * 10.0.2.2 is the IP address of the host from the point of view of the app build environment (QEMU VM). 38 | * 8443 is the host port which is forwarded to the SSL port (=433) of the ctrlX COREvirtual 39 | * 40 | * 41 | * IMPORTANT: 42 | * You need not change the parameter settings before building a snap and installing the snap on a ctrlX CORE. 43 | * The method get_connection_string detects the snap environment and uses automatically inter process communication. 44 | * Therefor the connection string to the ctrlX Datalayer is: 45 | * 46 | * "ipc://" 47 | * 48 | */ 49 | 50 | #include 51 | #include 52 | 53 | #include "comm/datalayer/datalayer.h" 54 | #include "comm/datalayer/datalayer_system.h" 55 | 56 | //! Retrieve environment variable SNAP 57 | static const char* snapPath() 58 | { 59 | return std::getenv("SNAP"); 60 | } 61 | 62 | //! Test if code is runnning in snap environment 63 | static bool isSnap() 64 | { 65 | return snapPath() != nullptr; 66 | } 67 | 68 | //! Get Datalayer connection string 69 | //! @param[in] ip IP address of the ctrlX CORE: 10.0.2.2 is ctrlX COREvirtual with port forwarding 70 | //! @param[in] user User name 71 | //! @param[in] password The password 72 | //! @param[in] sslPort The port number for SSL: 8443 if ctrlX COREvirtual with port forwarding 8443:443 73 | //! @result Connection string 74 | static std::string getConnectionString( 75 | const std::string& ip = "10.0.2.2", 76 | const std::string& user = "boschrexroth", 77 | const std::string& password = "boschrexroth", 78 | int sslPort = 8443) 79 | { 80 | if (isSnap()) 81 | { 82 | std::cout << "INFO Is snap" << std::endl; 83 | return DL_IPC; 84 | } 85 | 86 | std::string connectionString = DL_TCP + user + std::string(":") + password + std::string("@") + ip; 87 | 88 | if (443 == sslPort) 89 | { 90 | return connectionString; 91 | } 92 | 93 | return connectionString + std::string("?sslport=") + std::to_string(sslPort); 94 | } 95 | 96 | //! Get Datalayer Client instance 97 | //! @param[in] datalayerSystem Datalayer.System instance 98 | //! @param[in] ip IP address of the ctrlX CORE: 10.0.2.2 is ctrlX COREvirtual with port forwarding 99 | //! @param[in] user User name 100 | //! @param[in] password The password 101 | //! @param[in] sslPort The port number for SSL: 8443 if ctrlX COREvirtual with port forwarding 8443:443 102 | //! @result IClient instance or nullptr on error 103 | static comm::datalayer::IClient* getClient(comm::datalayer::DatalayerSystem& datalayerSystem, 104 | const std::string& ip = "10.0.2.2", 105 | const std::string& user = "boschrexroth", 106 | const std::string& password = "boschrexroth", int sslPort = 8443) 107 | { 108 | std::string connectionString = getConnectionString(ip, user, password, sslPort); 109 | comm::datalayer::IClient* client = datalayerSystem.factory()->createClient(connectionString); 110 | if (client->isConnected()) 111 | { 112 | return client; 113 | } 114 | 115 | delete client; 116 | 117 | return nullptr; 118 | } 119 | 120 | //! Get Datalayer Provider instance 121 | //! @param[in] datalayerSystem Datalayer.System instance 122 | //! @param[in] ip IP address of the ctrlX CORE: 10.0.2.2 is ctrlX COREvirtual with port forwarding 123 | //! @param[in] user User name 124 | //! @param[in] password The password 125 | //! @param[in] sslPort The port number for SSL: 8443 if ctrlX COREvirtual with port forwarding 8443:443 126 | //! @result IProvider instance or nullptr on error 127 | static comm::datalayer::IProvider* getProvider(comm::datalayer::DatalayerSystem& datalayerSystem, 128 | const std::string& ip = "10.0.2.2", 129 | const std::string& user = "boschrexroth", 130 | const std::string& password = "boschrexroth", int sslPort = 8443) 131 | { 132 | std::string connectionString = getConnectionString(ip, user, password, sslPort); 133 | comm::datalayer::IProvider* provider = datalayerSystem.factory()->createProvider(connectionString); 134 | if (provider->start() == DL_OK && provider->isConnected()) 135 | { 136 | return provider; 137 | } 138 | 139 | delete provider; 140 | 141 | return nullptr; 142 | } 143 | 144 | #endif 145 | -------------------------------------------------------------------------------- /simple-talker-dl-cpp/src/app/src/subscriber_member_function.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | 25 | #include "rclcpp/rclcpp.hpp" 26 | #include "std_msgs/msg/string.hpp" 27 | 28 | #include "comm/datalayer/datalayer.h" 29 | #include "comm/datalayer/datalayer_system.h" 30 | 31 | using namespace std::chrono_literals; 32 | 33 | 34 | 35 | // Add some signal Handling so we are able to abort the program with sending sigint 36 | static bool g_endProcess = false; 37 | 38 | static void signalHandler(int signal) 39 | { 40 | std::cout << "signal: " << signal << std::endl; 41 | g_endProcess = true; 42 | // Clean up datalayer instances so that process ends properly 43 | // Attention: Doesn't return if any provider or client instance is still runnning 44 | 45 | } 46 | //! Retrieve environment variable SNAP 47 | //! @result The content of SNAP ales nullptr if not available 48 | static const char* snapPath() 49 | { 50 | return std::getenv("SNAP"); 51 | } 52 | 53 | //! Test if code is runnning in snap environment 54 | //! @result True if running snap environment 55 | static bool isSnap() 56 | { 57 | return snapPath() != nullptr; 58 | } 59 | 60 | //! Get Datalayer connection string 61 | //! @param[in] ip IP address of the ctrlX CORE: 10.0.2.2 is ctrlX COREvirtual with port forwarding 62 | //! @param[in] user User name 63 | //! @param[in] password The password 64 | //! @param[in] sslPort The port number for SSL: 8443 if ctrlX COREvirtual with port forwarding 8443:443 65 | //! @result Connection string 66 | static std::string getConnectionString( 67 | const std::string& ip = "10.0.2.2", 68 | const std::string& user = "boschrexroth", 69 | const std::string& password = "boschrexroth", 70 | int sslPort = 8443) 71 | { 72 | if (isSnap()) 73 | { 74 | return DL_IPC; 75 | } 76 | 77 | std::string connectionString = DL_TCP + user + std::string(":") + password + std::string("@") + ip; 78 | 79 | if (443 == sslPort) 80 | { 81 | return connectionString; 82 | } 83 | 84 | return connectionString + std::string("?sslport=") + std::to_string(sslPort); 85 | } 86 | 87 | class MinimalPublisher : public rclcpp::Node 88 | { 89 | rclcpp::Publisher::SharedPtr m_publisher; 90 | 91 | public: 92 | MinimalPublisher() 93 | : Node("minimal_publisher") 94 | { 95 | m_publisher = this->create_publisher("ros2_simple_talker_cpp", 10); 96 | } 97 | 98 | /// @brief 99 | void myprint(const std::string& input) 100 | 101 | { 102 | auto message = std_msgs::msg::String(); 103 | message.data = "CPU Percentage: " + input; 104 | RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message.data.c_str()); 105 | m_publisher->publish(message); 106 | } 107 | }; 108 | 109 | int main(int argc, char * argv[]) 110 | { 111 | std::signal(SIGINT, signalHandler); 112 | // Initialize ROS 2 113 | rclcpp::init(argc, argv); 114 | MinimalPublisher pippo; 115 | 116 | std::cout << "INFO Starting ctrlX Data Layer system (without broker)" << std::endl; 117 | comm::datalayer::DatalayerSystem datalayerSystem; 118 | datalayerSystem.start(false); 119 | 120 | auto connectionString = getConnectionString(); // default: ctrlX CORE or ctrlX COREvirtual with Network Adpater 121 | std::cout << "INFO Creating ctrlX Data Layer client connection to " << connectionString << " ..." << std::endl; 122 | auto dataLayerClient = datalayerSystem.factory()->createClient(connectionString); 123 | 124 | int counter = 1; 125 | while (dataLayerClient->isConnected() && g_endProcess == false) 126 | { 127 | std::cout << "Loop #" << counter++ << std::endl; 128 | 129 | //Synchronous read of a ctrlX Data Layer node with a simple data type 130 | auto cpuUtilisationPercentAddress = "framework/metrics/system/cpu-utilisation-percent"; 131 | comm::datalayer::Variant cpuUtilisationPercentValue; 132 | std::cout << "INFO Reading " << cpuUtilisationPercentAddress << " synchronously..." << std::endl; 133 | auto result = dataLayerClient->readSync(cpuUtilisationPercentAddress, &cpuUtilisationPercentValue); 134 | if (result != DL_OK){ 135 | std::cout <<"WARN Reading " << cpuUtilisationPercentAddress << " failed with: " << result.toString() << std::endl; 136 | } 137 | else 138 | { 139 | if (cpuUtilisationPercentValue.getType() == comm::datalayer::VariantType::FLOAT64) 140 | { 141 | std::cout << "INFO Value of " << cpuUtilisationPercentAddress << ": " << double(cpuUtilisationPercentValue) << " %" << std::endl; 142 | auto str = std::to_string(double(cpuUtilisationPercentValue)); 143 | pippo.myprint(str); 144 | } 145 | else 146 | { 147 | std::cout << "WARN Value of " << cpuUtilisationPercentAddress << " has unexpected type: " << cpuUtilisationPercentValue.typeAsString() << std::endl; 148 | } 149 | } 150 | 151 | std::cout << "INFO Sleeping..." << std::endl; 152 | sleep(2); 153 | } 154 | 155 | std::cout << "ERROR ctrlX Data Layer connection is broken" << std::endl; 156 | 157 | delete dataLayerClient; 158 | datalayerSystem.stop(); 159 | 160 | return 1; // We exit because an error happend 161 | } -------------------------------------------------------------------------------- /simple-listener-dl-cpp/src/app/src/subscriber_member_function.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | 24 | #include "rclcpp/rclcpp.hpp" 25 | #include "std_msgs/msg/string.hpp" 26 | 27 | #include "comm/datalayer/datalayer.h" 28 | #include "comm/datalayer/datalayer_system.h" 29 | 30 | #include "ctrlx_datalayer_helper.h" 31 | 32 | using std::placeholders::_1; 33 | 34 | 35 | using comm::datalayer::IProviderNode; 36 | 37 | // Basic class Provider node interface for providing data to the system 38 | class MyProviderNode: public IProviderNode 39 | { 40 | private: 41 | comm::datalayer::Variant m_data; 42 | 43 | public: 44 | MyProviderNode(comm::datalayer::Variant data) 45 | : m_data(data) 46 | {}; 47 | void setString(const std::string& input) 48 | { 49 | m_data.setValue(input); 50 | 51 | } 52 | virtual ~MyProviderNode() override {}; 53 | 54 | // Create function of an object. Function will be called whenever a object should be created. 55 | virtual void onCreate(const std::string& address, const comm::datalayer::Variant* data, const comm::datalayer::IProviderNode::ResponseCallback& callback) override 56 | { 57 | callback(comm::datalayer::DlResult::DL_FAILED, nullptr); 58 | } 59 | 60 | // Read function of a node. Function will be called whenever a node should be read. 61 | virtual void onRead(const std::string& address, const comm::datalayer::Variant* data, const comm::datalayer::IProviderNode::ResponseCallback& callback) override 62 | { 63 | comm::datalayer::Variant dataRead; 64 | dataRead = m_data; 65 | callback(comm::datalayer::DlResult::DL_OK, &dataRead); 66 | } 67 | 68 | // Write function of a node. Function will be called whenever a node should be written. 69 | virtual void onWrite(const std::string& address, const comm::datalayer::Variant* data, const comm::datalayer::IProviderNode::ResponseCallback& callback) override 70 | { 71 | std::cout << "INFO onWrite " << address << std::endl; 72 | 73 | if (data->getType() != m_data.getType()) 74 | { 75 | callback(comm::datalayer::DlResult::DL_TYPE_MISMATCH, nullptr); 76 | } 77 | 78 | m_data = *data; 79 | callback(comm::datalayer::DlResult::DL_OK, data); 80 | } 81 | 82 | // Remove function for an object. Function will be called whenever a object should be removed. 83 | virtual void onRemove(const std::string& address, const comm::datalayer::IProviderNode::ResponseCallback& callback) override 84 | { 85 | callback(comm::datalayer::DlResult::DL_FAILED, nullptr); 86 | } 87 | 88 | // Browse function of a node. Function will be called to determine children of a node. 89 | virtual void onBrowse(const std::string& address, const comm::datalayer::IProviderNode::ResponseCallback& callback) override 90 | { 91 | callback(comm::datalayer::DlResult::DL_FAILED, nullptr); 92 | } 93 | 94 | // Read function of metadata of an object. Function will be called whenever a node should be written. 95 | virtual void onMetadata(const std::string& address, const comm::datalayer::IProviderNode::ResponseCallback& callback) override 96 | { 97 | // Keep this comment! Can be used as sample creating metadata programmatically. 98 | // callback(comm::datalayer::DlResult::DL_OK, &_metaData); 99 | 100 | // Take metadata from metadata.mddb 101 | callback(comm::datalayer::DlResult::DL_FAILED, nullptr); 102 | } 103 | }; 104 | 105 | 106 | class MinimalSubscriber : public rclcpp::Node 107 | { 108 | comm::datalayer::Variant m_myString; 109 | comm::datalayer::DatalayerSystem m_datalayerSystem; 110 | std::unique_ptr m_provider; 111 | std::unique_ptr m_pippo; 112 | rclcpp::Subscription::SharedPtr m_subscription; 113 | 114 | public: 115 | 116 | MinimalSubscriber() 117 | : Node("minimal_subscriber") 118 | , m_pippo(std::make_unique(MyProviderNode(m_myString))) 119 | { 120 | m_subscription = this->create_subscription( 121 | "ros2_simple_talker_cpp", 10, std::bind(&MinimalSubscriber::topic_callback, this, _1)); 122 | 123 | // Starts the ctrlX Data Layer system without a new broker because one broker is already running on ctrlX CORE 124 | m_datalayerSystem.start(false); 125 | m_provider.reset(getProvider(m_datalayerSystem)); // ctrlX CORE (virtual) 126 | m_pippo->setString("No Message yet"); 127 | std::cout << "INFO Register node 'ros/listenercpp/mymessage' " << std::endl; 128 | comm::datalayer::DlResult result = m_provider->registerNode("ros/listenercpp/mymessage",m_pippo.get()); 129 | if (STATUS_FAILED(result)) 130 | { 131 | std::cout << "WARN Register node 'sdk-cpp-registernode/myString' failed with: " << result.toString() << std::endl; 132 | } 133 | } 134 | 135 | ~MinimalSubscriber() 136 | { 137 | std::cout << __func__ << std::endl; 138 | m_provider->stop(); 139 | m_provider = nullptr; 140 | m_datalayerSystem.stop(); 141 | } 142 | 143 | private: 144 | void topic_callback(const std_msgs::msg::String & msg) const 145 | { 146 | RCLCPP_INFO(this->get_logger(), "I heard: '%s'", msg.data.c_str()); 147 | m_pippo->setString( msg.data.c_str() ); 148 | } 149 | }; 150 | 151 | int main(int argc, char * argv[]) 152 | { 153 | rclcpp::init(argc, argv); 154 | { 155 | std::shared_ptr node = std::make_shared(); 156 | rclcpp::spin(node); 157 | } 158 | rclcpp::shutdown(); 159 | return 0; 160 | } 161 | -------------------------------------------------------------------------------- /simple-talker-dl-py/src/app/ros2/datalayer_reader_ros2_publisher.py: -------------------------------------------------------------------------------- 1 | """Read the ctrlX Data Layer value and publish it via ROS 2 message.""" 2 | 3 | # SPDX-FileCopyrightText: Bosch Rexroth AG 4 | # 5 | # SPDX-License-Identifier: MIT 6 | 7 | import rclpy 8 | from rclpy.node import Node 9 | 10 | import std_msgs.msg 11 | 12 | import ctrlxdatalayer 13 | from ctrlxdatalayer.variant import Result, Variant 14 | 15 | from ctrlx_datalayer.ctrlx_datalayer_helper import get_client 16 | 17 | # Assignment table 'ROS 2 Message Data Type' <-> 'ctrlX Data Layer Variant 18 | # gettter method'. 19 | CTRLX_TO_ROS2_CONVERTERS = { 20 | 'INT8': { 21 | 'ctrlxGetter': Variant.get_int8, 22 | 'msgDataType': std_msgs.msg.Int8}, 23 | 'INT16': { 24 | 'ctrlxGetter': Variant.get_int16, 25 | 'msgDataType': std_msgs.msg.Int16}, 26 | 'INT32': { 27 | 'ctrlxGetter': Variant.get_int32, 28 | 'msgDataType': std_msgs.msg.Int32}, 29 | 'INT64': { 30 | 'ctrlxGetter': Variant.get_int64, 31 | 'msgDataType': std_msgs.msg.Int64}, 32 | 'UINT8': { 33 | 'ctrlxGetter': Variant.get_uint8, 34 | 'msgDataType': std_msgs.msg.UInt8}, 35 | 'UINT16': { 36 | 'ctrlxGetter': Variant.get_uint16, 37 | 'msgDataType': std_msgs.msg.UInt16}, 38 | 'UINT32': { 39 | 'ctrlxGetter': Variant.get_uint32, 40 | 'msgDataType': std_msgs.msg.UInt32}, 41 | 'UINT64': { 42 | 'ctrlxGetter': Variant.get_uint64, 43 | 'msgDataType': std_msgs.msg.UInt64}, 44 | 'FLOAT32': { 45 | 'ctrlxGetter': Variant.get_float32, 46 | 'msgDataType': std_msgs.msg.Float32}, 47 | 'FLOAT64': { 48 | 'ctrlxGetter': Variant.get_float64, 49 | 'msgDataType': std_msgs.msg.Float64}, 50 | 'STRING': { 51 | 'ctrlxGetter': Variant.get_string, 52 | 'msgDataType': std_msgs.msg.String}, 53 | 'BOOL8': { 54 | 'ctrlxGetter': Variant.get_bool8, 55 | 'msgDataType': std_msgs.msg.Bool}, 56 | 'ARRAY_INT8': { 57 | 'ctrlxGetter': Variant.get_array_int8, 58 | 'msgDataType': std_msgs.msg.Int8MultiArray}, 59 | 'ARRAY_INT16': { 60 | 'ctrlxGetter': Variant.get_array_int16, 61 | 'msgDataType': std_msgs.msg.Int16MultiArray}, 62 | 'ARRAY_INT32': { 63 | 'ctrlxGetter': Variant.get_array_int32, 64 | 'msgDataType': std_msgs.msg.Int32MultiArray}, 65 | 'ARRAY_INT64': { 66 | 'ctrlxGetter': Variant.get_array_int64, 67 | 'msgDataType': std_msgs.msg.Int64MultiArray}, 68 | 'UInt8MultiArray': { 69 | 'ctrlxGetter': Variant.get_array_uint8, 70 | 'msgDataType': std_msgs.msg.UInt8MultiArray}, 71 | 'UInt16MultiArray': { 72 | 'ctrlxGetter': Variant.get_array_uint16, 73 | 'msgDataType': std_msgs.msg.UInt16MultiArray}, 74 | 'UInt32MultiArray': { 75 | 'ctrlxGetter': Variant.get_array_uint32, 76 | 'msgDataType': std_msgs.msg.UInt32MultiArray}, 77 | 'UInt64MultiArray': { 78 | 'ctrlxGetter': Variant.get_array_uint64, 79 | 'msgDataType': std_msgs.msg.UInt64MultiArray}, 80 | 'Float32MultiArray': { 81 | 'ctrlxGetter': Variant.get_array_float32, 82 | 'msgDataType': std_msgs.msg.Float32MultiArray}, 83 | 'Float64MultiArray': { 84 | 'ctrlxGetter': Variant.get_array_float64, 85 | 'msgDataType': std_msgs.msg.Float64MultiArray}} 86 | 87 | 88 | class DataLayerReaderRos2Publisher(Node): 89 | """ 90 | Class DataLayerReaderRos2Publisher. 91 | 92 | Reads a ctrlX Data Layer varinat value and sends it via ROS 2 message. 93 | """ 94 | 95 | def __init__(self, dl_address, ros2_topic): 96 | """ 97 | Initialize an instance. 98 | 99 | Constructor of the class. 100 | """ 101 | self.dl_address = dl_address 102 | self.ros2_topic = ros2_topic 103 | 104 | self.datalayer_system = None 105 | self.datalayer_client = None 106 | self.getter_method = None 107 | self.ros2_msg_data_type = None 108 | self.ros2_publisher = None 109 | self.timer = None 110 | 111 | def read_data_layer_value(self): 112 | """ 113 | Read a ctrlX Data Layer value. 114 | 115 | Returns the value as variant. 116 | """ 117 | result, variant = self.datalayer_client.read_sync(self.dl_address) 118 | if result != Result.OK: 119 | print('ERROR Reading ctrlX Data Layer node', self.dl_address, 'failed', result) 120 | return None 121 | 122 | return variant 123 | 124 | def start(self): 125 | """ 126 | Start running. 127 | 128 | Connects to the ctrlX Data Layer, initializes the rclpy super class 129 | instance and starts the timer. 130 | """ 131 | self.datalayer_system = ctrlxdatalayer.system.System('') 132 | self.datalayer_system.start(False) 133 | 134 | print('INFO Creating ctrlX Data Layer connnection') 135 | self.datalayer_client, connection_string = get_client(self.datalayer_system) 136 | if self.datalayer_client is None: 137 | print('ERROR Creating ctrlX Data Layer connnection to', connection_string, 'failed') 138 | return False 139 | 140 | variant = self.read_data_layer_value() 141 | if variant is None: 142 | return False 143 | 144 | print('INFO Initializing ROS 2 node ctrlxReaderRos2Talker') 145 | super().__init__('ctrlxReaderRos2Talker') 146 | 147 | ctrlx_to_ros2_converter = CTRLX_TO_ROS2_CONVERTERS[variant.get_type().name] 148 | print('INFO ros2_msg', ctrlx_to_ros2_converter) 149 | 150 | self.getter_method = ctrlx_to_ros2_converter['ctrlxGetter'] 151 | self.ros2_msg_data_type = ctrlx_to_ros2_converter['msgDataType'] 152 | print('INFO Creating ROS 2 publisher: type', self.ros2_msg_data_type, 'topic', self.ros2_topic) 153 | self.ros2_publisher = self.create_publisher(self.ros2_msg_data_type, self.ros2_topic, 10) 154 | if self.ros2_publisher is None: 155 | print('ERROR Creating ROS 2 publisher failed') 156 | return False 157 | 158 | timer_period = 1.0 # seconds 159 | self.timer = self.create_timer(timer_period, self.timer_callback) 160 | 161 | return True 162 | 163 | def timer_callback(self): 164 | """ 165 | Handle timer tick. 166 | 167 | Reads a ctrlX Data Layer values and sends it. 168 | """ 169 | variant = self.read_data_layer_value() 170 | if variant is None: 171 | return 172 | 173 | ros2_msg = self.ros2_msg_data_type() 174 | ros2_msg.data = self.getter_method(variant) 175 | 176 | with variant: 177 | self.get_logger().info('Publishing "%s"' % ros2_msg.data) 178 | self.ros2_publisher.publish(ros2_msg) 179 | 180 | def stop(self): 181 | """ 182 | Stop the app. 183 | 184 | Stops the ctrlX Data Layer and the timer. 185 | """ 186 | self.datalayer_system = ctrlxdatalayer.system.System('') 187 | self.datalayer_system.stop(False) 188 | 189 | if self.timer is not None: 190 | self.destroy_timer(self.timer) 191 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ctrlX AUTOMATION Software Development Kit for ROS 2 2 | 3 | This is the Software Development Kit (SDK) to build ROS 2 Applications, that can run on industrial devices that are based on the ctrlX OS platform. 4 | 5 | The **Robot Operating System (ROS)** is an open source robotics software framework that help you build robot applications. 6 | **ctrlX OS** is an industrial grade realtime platform based on Linux which is available for several industrial hardware devices and features an app-based modular architecture that allows you to install additional functionality. This includes apps for industrial fieldbus communication, machine automation, programmable logic control (PLC) and other automation software which can also be found ready-to-run in the [ctrlX Store](https://developer.community.boschrexroth.com/). 7 | 8 | Please note, that this is the first version of the ROS 2 SDK. You may expect more samples and extensions over the course of the next months. 9 | 10 | ## Getting Started 11 | 12 | As a prerequisite you should get yourself familiar with: 13 | 14 | * ROS 2 and its underlying architecture using the official ROS 2 documentation at: 15 | * The [ctrlX AUTOMATION Ecosystem](https://ctrlx-automation.com/) and the architecture of ctrlX OS as well as devices which are capable to run ctrlX OS. E.g. ctrlX CORE devices from [Bosch Rexroth](https://www.boschrexroth.com/). 16 | * The [ctrlX AUTOMATION SDK](https://github.com/boschrexroth/ctrlx-automation-sdk) which is the underlying SDK that allows you to create any kind of App for ctrlX OS and is the foundation for the ctrlX AUTOMATION Software Development Kit for ROS 2. [Link to SDK Documentation](https://boschrexroth.github.io/ctrlx-automation-sdk/) 17 | 18 | ## Usage 19 | 20 | This SDK builds on top of the [ctrlX AUTOMATION SDK](https://github.com/boschrexroth/ctrlx-automation-sdk) to make apps for ctrlX OS, which is itself based on Ubuntu Core Distribution and a Linux kernel with PREEMPT_RT patch. 21 | 22 | ctrlX OS, Ubuntu Core, as well as ROS 2 are released as *distributions*. This release of the SDK is intended to be used with: 23 | 24 | * ctrlX OS 2.x (Includes Ubuntu Core 22) 25 | * ROS 2 [Humble Hawksbill](https://docs.ros.org/en/humble/) 26 | 27 | All projects use [Visual Studio Code](https://code.visualstudio.com/) as editor. 28 | 29 | ### ROS 2 Humble Base Snap 30 | 31 | To build and deploy a ROS 2 application to ctrlX OS it needs to be package as [snap](https://ubuntu.com/core/services/guide/snaps-intro). In order to make your development process as efficient as possible we recommend splitting your ROS 2 deployment into at least two snaps. A so-called *base snap* is used to encapsulate the ROS 2 runtime as well as libraries which are dependencies to your application. The *base snap* is installed on ctrlX OS once and provides the compiled runtime and libraries to one or more ROS 2 application snaps which hold your business logic. Following this approach you can reduce build times and resource footprint on the device by sharing the ROS 2 dependencies. 32 | 33 | For details have a look at the instructions for the [ROS 2 Humble Base Snap](ros2-base-humble-deb/README.md) which also shows you how to compile ROS 2 for ctrlX OS. 34 | 35 | If you nevertheless want to go with a single app, then use the *base snap* and integrate your ROS 2 application directly. 36 | 37 | ## Samples 38 | 39 | This SDK contains also multiple project examples to show the usage of ROS 2. All examples build on top of the *base snap*. 40 | 41 | ### ROS 2 Humble Applications in C++ 42 | 43 | #### Learn how to package your application as snap 44 | 45 | This example is based on the official ROS 2 Tutorial and adjusted to run on ctrlX OS together with the *base snap*. You can find the original source code at [ROS 2 Humble Tutorials - Writing a simple publisher and subscriber (C++)](https://docs.ros.org/en/humble/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Cpp-Publisher-And-Subscriber.html#writing-a-simple-publisher-and-subscriber-c) 46 | 47 | * [`simple-talker-cpp/`](simple-talker-cpp/README.md) contains the snap version of the described publisher (talker) 48 | * [`simple-listener-cpp/`](simple-listener-cpp/README.md) contains the snap version of the described subscriber (listener) 49 | 50 | #### Learn how to access the ctrlX Data Layer from your application 51 | 52 | the ctrlX Data Layer is the realtime message broker that runs on ctrlX OS. It is used by all ctrlX Apps to publish and exchange variables, types, methods and programs. In the ctrlX Data Layer you can find all device, process, fieldbus and periphery data. You can connect to the ctrlX Data Layer via TCP/IP or IPC. 53 | 54 | * [`simple-talker-dl-cpp/`](simple-talker-dl-cpp/README.md) read from ctrlX Data Layer and publish as ROS message (talker) 55 | * [`simple-listener-dl-cpp/`](simple-listener-dl-cpp/README.md) subscribe to ROS message and publish in ctrlX Data Layer (listener) 56 | 57 | ### ROS 2 Humble Applications in Python 58 | 59 | #### Writing a Simple Publisher and Subscriber (Python) 60 | 61 | This example is based on the official ROS 2 Tutorial and adjusted to run on ctrlX OS together with the *base snap*. You can find the original source code at [ROS 2 Humble Tutorials - Writing a simple publisher and subscriber (Python)](https://docs.ros.org/en/humble/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Py-Publisher-And-Subscriber.html) 62 | 63 | * [`simple-talker-py/`](simple-talker-py/README.md) contains the snap version of the described publisher (talker) 64 | * [`simple-listener-py/`](simple-listener-py/README.md) contains the snap version of the described subscriber (listener) 65 | 66 | #### Writing a Simple Publisher and Subscriber with ctrlX Data Layer Access (Python) 67 | 68 | Both sample projects are based on the same official ROS 2 tutorial as mentioned above. Additionally, the example is extended with access to the ctrlX Data Layer using the ctrlX SDK. 69 | 70 | * [`simple-talker-dl-py/`](simple-talker-dl-py/README.md) Reads a Data Layer value and publishes it as ROS 2 message under a specific topic. 71 | * [`simple-listener-dl-py/`](simple-listener-dl-py/README.md) Subscribes messages of the topic, receives the value and writes it into the ctrlX Data Layer. 72 | 73 | ## Support 74 | 75 | This repository is provided and maintained by [Bosch Rexroth](https://www.boschrexroth.com). Feel free to check out and be part of the [ctrlX AUTOMATION Community](https://ctrlx-automation.com/community). Get additional support, e.g. related to Bosch Rexroth Devices, Apps, SDKs and Services, or leave some ideas and feedback. 76 | 77 | To report bugs, request changes and discuss new ideas you may also have a look at the issue tracker of this repository: 78 | 79 | 80 | ## Important directions for use 81 | 82 | ### Areas of use and application 83 | 84 | The content (e.g. source code and related documents) of this repository is intended to be used for configuration, parameterization, programming or diagnostics in combination with selected Bosch Rexroth ctrlX AUTOMATION devices. 85 | Additionally, the specifications given in the "Areas of Use and Application" for ctrlX AUTOMATION devices used with the content of this repository do also apply. 86 | 87 | ### Unintended use 88 | 89 | Any use of the source code and related documents of this repository in applications other than those specified above or under operating conditions other than those described in the documentation and the technical specifications is considered as "unintended". Furthermore, this software must not be used in any application areas not expressly approved by Bosch Rexroth. 90 | 91 | ## Changelog 92 | 93 | ```text 94 | * 2025-01-16: 2.4.0 - update to snapcraft version 7.x 95 | * 2024-12-06: 2.3.0 - update and fixed runtime environment 96 | * 2024-12-05: 2.2.0 - Merge with https://github.com/boschrexroth/ctrlx-automation-sdk-ros2 97 | * 2024-06-28: 2.0.1 - Improve documentation, use symbolic links for build scripts 98 | * 2023-09-01: 2.0.0 - Initial release for ROS 2 Humble Hawksbill. 99 | ``` 100 | 101 | ## About 102 | 103 | SPDX-FileCopyrightText: Copyright (c) 2025 Bosch Rexroth AG 104 | 105 | 106 | 107 | ## Licenses 108 | 109 | SPDX-License-Identifier: MIT 110 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.toptal.com/developers/gitignore/api/go,c++,linux,csharp,windows,snapcraft,macos 3 | # Edit at https://www.toptal.com/developers/gitignore?templates=go,c++,linux,csharp,windows,snapcraft,macos 4 | 5 | ### C++ ### 6 | # Prerequisites 7 | *.d 8 | 9 | # Compiled Object files 10 | *.slo 11 | *.lo 12 | *.o 13 | *.obj 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Linker files 20 | *.ilk 21 | 22 | # Debugger Files 23 | *.pdb 24 | 25 | # Compiled Dynamic libraries 26 | *.so 27 | *.dylib 28 | *.dll 29 | 30 | # Fortran module files 31 | *.mod 32 | *.smod 33 | 34 | # Compiled Static libraries 35 | *.lai 36 | *.la 37 | *.a 38 | *.lib 39 | 40 | # Executables 41 | *.exe 42 | *.out 43 | *.app 44 | 45 | ### Csharp ### 46 | ## Ignore Visual Studio temporary files, build results, and 47 | ## files generated by popular Visual Studio add-ons. 48 | ## 49 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 50 | 51 | # User-specific files 52 | *.rsuser 53 | *.suo 54 | *.user 55 | *.userosscache 56 | *.sln.docstates 57 | 58 | # User-specific files (MonoDevelop/Xamarin Studio) 59 | *.userprefs 60 | 61 | # Mono auto generated files 62 | mono_crash.* 63 | 64 | # Build results 65 | [Dd]ebug/ 66 | [Dd]ebugPublic/ 67 | [Rr]elease/ 68 | [Rr]eleases/ 69 | x64/ 70 | x86/ 71 | [Ww][Ii][Nn]32/ 72 | [Aa][Rr][Mm]/ 73 | [Aa][Rr][Mm]64/ 74 | bld/ 75 | [Bb]in/ 76 | [Oo]bj/ 77 | [Ll]og/ 78 | [Ll]ogs/ 79 | 80 | # Visual Studio 2015/2017 cache/options directory 81 | .vs/ 82 | # Uncomment if you have tasks that create the project's static files in wwwroot 83 | #wwwroot/ 84 | 85 | # Visual Studio 2017 auto generated files 86 | Generated\ Files/ 87 | 88 | # MSTest test Results 89 | [Tt]est[Rr]esult*/ 90 | [Bb]uild[Ll]og.* 91 | 92 | # NUnit 93 | *.VisualState.xml 94 | TestResult.xml 95 | nunit-*.xml 96 | 97 | # Build Results of an ATL Project 98 | [Dd]ebugPS/ 99 | [Rr]eleasePS/ 100 | dlldata.c 101 | 102 | # Benchmark Results 103 | BenchmarkDotNet.Artifacts/ 104 | 105 | # .NET Core 106 | project.lock.json 107 | project.fragment.lock.json 108 | artifacts/ 109 | 110 | # ASP.NET Scaffolding 111 | ScaffoldingReadMe.txt 112 | 113 | # StyleCop 114 | StyleCopReport.xml 115 | 116 | # Files built by Visual Studio 117 | *_i.c 118 | *_p.c 119 | *_h.h 120 | *.meta 121 | *.iobj 122 | *.ipdb 123 | *.pgc 124 | *.pgd 125 | *.rsp 126 | *.sbr 127 | *.tlb 128 | *.tli 129 | *.tlh 130 | *.tmp 131 | *.tmp_proj 132 | *_wpftmp.csproj 133 | *.log 134 | *.vspscc 135 | *.vssscc 136 | .builds 137 | *.pidb 138 | *.svclog 139 | *.scc 140 | 141 | # Chutzpah Test files 142 | _Chutzpah* 143 | 144 | # Visual C++ cache files 145 | ipch/ 146 | *.aps 147 | *.ncb 148 | *.opendb 149 | *.opensdf 150 | *.sdf 151 | *.cachefile 152 | *.VC.db 153 | *.VC.VC.opendb 154 | 155 | # Visual Studio profiler 156 | *.psess 157 | *.vsp 158 | *.vspx 159 | *.sap 160 | 161 | # Visual Studio Trace Files 162 | *.e2e 163 | 164 | # TFS 2012 Local Workspace 165 | $tf/ 166 | 167 | # Guidance Automation Toolkit 168 | *.gpState 169 | 170 | # ReSharper is a .NET coding add-in 171 | _ReSharper*/ 172 | *.[Rr]e[Ss]harper 173 | *.DotSettings.user 174 | 175 | # TeamCity is a build add-in 176 | _TeamCity* 177 | 178 | # DotCover is a Code Coverage Tool 179 | *.dotCover 180 | 181 | # AxoCover is a Code Coverage Tool 182 | .axoCover/* 183 | !.axoCover/settings.json 184 | 185 | # Coverlet is a free, cross platform Code Coverage Tool 186 | coverage*.[ji][sn][of][no] 187 | coverage*.xml 188 | 189 | # Visual Studio code coverage results 190 | *.coverage 191 | *.coveragexml 192 | 193 | # NCrunch 194 | _NCrunch_* 195 | .*crunch*.local.xml 196 | nCrunchTemp_* 197 | 198 | # MightyMoose 199 | *.mm.* 200 | AutoTest.Net/ 201 | 202 | # Web workbench (sass) 203 | .sass-cache/ 204 | 205 | # Installshield output folder 206 | [Ee]xpress/ 207 | 208 | # DocProject is a documentation generator add-in 209 | DocProject/buildhelp/ 210 | DocProject/Help/*.HxT 211 | DocProject/Help/*.HxC 212 | DocProject/Help/*.hhc 213 | DocProject/Help/*.hhk 214 | DocProject/Help/*.hhp 215 | DocProject/Help/Html2 216 | DocProject/Help/html 217 | 218 | # Click-Once directory 219 | publish/ 220 | 221 | # Publish Web Output 222 | *.[Pp]ublish.xml 223 | *.azurePubxml 224 | # Note: Comment the next line if you want to checkin your web deploy settings, 225 | # but database connection strings (with potential passwords) will be unencrypted 226 | *.pubxml 227 | *.publishproj 228 | 229 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 230 | # checkin your Azure Web App publish settings, but sensitive information contained 231 | # in these scripts will be unencrypted 232 | PublishScripts/ 233 | 234 | # NuGet Packages 235 | *.nupkg 236 | # NuGet Symbol Packages 237 | *.snupkg 238 | # The packages folder can be ignored because of Package Restore 239 | **/[Pp]ackages/* 240 | # except build/, which is used as an MSBuild target. 241 | !**/[Pp]ackages/build/ 242 | # Uncomment if necessary however generally it will be regenerated when needed 243 | #!**/[Pp]ackages/repositories.config 244 | # NuGet v3's project.json files produces more ignorable files 245 | *.nuget.props 246 | *.nuget.targets 247 | 248 | # Microsoft Azure Build Output 249 | csx/ 250 | *.build.csdef 251 | 252 | # Microsoft Azure Emulator 253 | ecf/ 254 | rcf/ 255 | 256 | # Windows Store app package directories and files 257 | AppPackages/ 258 | BundleArtifacts/ 259 | Package.StoreAssociation.xml 260 | _pkginfo.txt 261 | *.appx 262 | *.appxbundle 263 | *.appxupload 264 | 265 | # Visual Studio cache files 266 | # files ending in .cache can be ignored 267 | *.[Cc]ache 268 | # but keep track of directories ending in .cache 269 | !?*.[Cc]ache/ 270 | 271 | # Others 272 | ClientBin/ 273 | ~$* 274 | *~ 275 | *.dbmdl 276 | *.dbproj.schemaview 277 | *.jfm 278 | *.pfx 279 | *.publishsettings 280 | orleans.codegen.cs 281 | 282 | # Including strong name files can present a security risk 283 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 284 | #*.snk 285 | 286 | # Since there are multiple workflows, uncomment next line to ignore bower_components 287 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 288 | #bower_components/ 289 | 290 | # RIA/Silverlight projects 291 | Generated_Code/ 292 | 293 | # Backup & report files from converting an old project file 294 | # to a newer Visual Studio version. Backup files are not needed, 295 | # because we have git ;-) 296 | _UpgradeReport_Files/ 297 | Backup*/ 298 | UpgradeLog*.XML 299 | UpgradeLog*.htm 300 | ServiceFabricBackup/ 301 | *.rptproj.bak 302 | 303 | # SQL Server files 304 | *.mdf 305 | *.ldf 306 | *.ndf 307 | 308 | # Business Intelligence projects 309 | *.rdl.data 310 | *.bim.layout 311 | *.bim_*.settings 312 | *.rptproj.rsuser 313 | *- [Bb]ackup.rdl 314 | *- [Bb]ackup ([0-9]).rdl 315 | *- [Bb]ackup ([0-9][0-9]).rdl 316 | 317 | # Microsoft Fakes 318 | FakesAssemblies/ 319 | 320 | # GhostDoc plugin setting file 321 | *.GhostDoc.xml 322 | 323 | # Node.js Tools for Visual Studio 324 | .ntvs_analysis.dat 325 | node_modules/ 326 | 327 | # Visual Studio 6 build log 328 | *.plg 329 | 330 | # Visual Studio 6 workspace options file 331 | *.opt 332 | 333 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 334 | *.vbw 335 | 336 | # Visual Studio LightSwitch build output 337 | **/*.HTMLClient/GeneratedArtifacts 338 | **/*.DesktopClient/GeneratedArtifacts 339 | **/*.DesktopClient/ModelManifest.xml 340 | **/*.Server/GeneratedArtifacts 341 | **/*.Server/ModelManifest.xml 342 | _Pvt_Extensions 343 | 344 | # Paket dependency manager 345 | .paket/paket.exe 346 | paket-files/ 347 | 348 | # FAKE - F# Make 349 | .fake/ 350 | 351 | # CodeRush personal settings 352 | .cr/personal 353 | 354 | # Python Tools for Visual Studio (PTVS) 355 | __pycache__/ 356 | *.pyc 357 | 358 | # Cake - Uncomment if you are using it 359 | # tools/** 360 | # !tools/packages.config 361 | 362 | # Tabs Studio 363 | *.tss 364 | 365 | # Telerik's JustMock configuration file 366 | *.jmconfig 367 | 368 | # BizTalk build output 369 | *.btp.cs 370 | *.btm.cs 371 | *.odx.cs 372 | *.xsd.cs 373 | 374 | # OpenCover UI analysis results 375 | OpenCover/ 376 | 377 | # Azure Stream Analytics local run output 378 | ASALocalRun/ 379 | 380 | # MSBuild Binary and Structured Log 381 | *.binlog 382 | 383 | # NVidia Nsight GPU debugger configuration file 384 | *.nvuser 385 | 386 | # MFractors (Xamarin productivity tool) working folder 387 | .mfractor/ 388 | 389 | # Local History for Visual Studio 390 | .localhistory/ 391 | 392 | # BeatPulse healthcheck temp database 393 | healthchecksdb 394 | 395 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 396 | MigrationBackup/ 397 | 398 | # Ionide (cross platform F# VS Code tools) working folder 399 | .ionide/ 400 | 401 | # Fody - auto-generated XML schema 402 | FodyWeavers.xsd 403 | 404 | ### Go ### 405 | # Binaries for programs and plugins 406 | *.exe~ 407 | 408 | # Test binary, built with `go test -c` 409 | *.test 410 | 411 | # Output of the go coverage tool, specifically when used with LiteIDE 412 | 413 | # Dependency directories (remove the comment below to include it) 414 | # vendor/ 415 | 416 | ### Go Patch ### 417 | /vendor/ 418 | /Godeps/ 419 | 420 | ### Linux ### 421 | 422 | # temporary files which can be created if a process still has a handle open of a deleted file 423 | .fuse_hidden* 424 | 425 | # KDE directory preferences 426 | .directory 427 | 428 | # Linux trash folder which might appear on any partition or disk 429 | .Trash-* 430 | 431 | # .nfs files are created when an open file is removed but is still being accessed 432 | .nfs* 433 | 434 | ### macOS ### 435 | # General 436 | .DS_Store 437 | .AppleDouble 438 | .LSOverride 439 | 440 | # Icon must end with two \r 441 | Icon 442 | 443 | 444 | # Thumbnails 445 | ._* 446 | 447 | # Files that might appear in the root of a volume 448 | .DocumentRevisions-V100 449 | .fseventsd 450 | .Spotlight-V100 451 | .TemporaryItems 452 | .Trashes 453 | .VolumeIcon.icns 454 | .com.apple.timemachine.donotpresent 455 | 456 | # Directories potentially created on remote AFP share 457 | .AppleDB 458 | .AppleDesktop 459 | Network Trash Folder 460 | Temporary Items 461 | .apdisk 462 | 463 | ### Snapcraft ### 464 | /parts/ 465 | /stage/ 466 | /prime/ 467 | *.snap 468 | /deb 469 | 470 | # Snapcraft global state tracking data(automatically generated) 471 | # https://forum.snapcraft.io/t/location-to-save-global-state/768 472 | /snap/.snapcraft/ 473 | 474 | # Source archive packed by `snapcraft cleanbuild` before pushing to the LXD container 475 | /*_source.tar.bz2 476 | 477 | ### Windows ### 478 | # Windows thumbnail cache files 479 | Thumbs.db 480 | Thumbs.db:encryptable 481 | ehthumbs.db 482 | ehthumbs_vista.db 483 | 484 | # Dump file 485 | *.stackdump 486 | 487 | # Folder config file 488 | [Dd]esktop.ini 489 | 490 | # Recycle Bin used on file shares 491 | $RECYCLE.BIN/ 492 | 493 | # Windows Installer files 494 | *.cab 495 | *.msi 496 | *.msix 497 | *.msm 498 | *.msp 499 | 500 | # Windows shortcuts 501 | *.lnk 502 | 503 | # End of https://www.toptal.com/developers/gitignore/api/go,c++,linux,csharp,windows,snapcraft,macos 504 | -------------------------------------------------------------------------------- /LICENSES/Apache-2.0.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | --------------------------------------------------------------------------------