├── .clang-format
├── .codespellignore
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ ├── feature_request.md
│ └── question.md
├── dependabot.yaml
└── workflows
│ ├── ci-format.yml
│ ├── ci-ros-lint.yml.backup
│ ├── docker.yml
│ ├── humble.yml
│ ├── humble_documentation.yml
│ ├── iron.yml
│ ├── iron_documentation.yml
│ ├── prerelease-rolling.yml
│ ├── rolling.yml
│ └── rolling_documentation.yml
├── .gitignore
├── .gitlab-ci.yml
├── .pre-commit-config.yaml
├── Dockerfile
├── README.md
├── canopen
├── CHANGELOG.rst
├── CMakeLists.txt
├── LICENSE
├── doxygen
│ └── Doxyfile
├── package.xml
└── sphinx
│ ├── Makefile
│ ├── _static
│ └── css
│ │ └── custom.css
│ ├── application
│ ├── prbt_robot.rst
│ └── trinamic.rst
│ ├── conf.py
│ ├── developers-guide
│ ├── architecture.rst
│ ├── design-objectives.rst
│ ├── new-device-manager.rst
│ ├── new-driver.rst
│ ├── new-master.rst
│ └── overview.rst
│ ├── images
│ ├── configuration-flow.png
│ ├── device-manager-usage.png
│ ├── device-manager.png
│ ├── prbt_rviz2.png
│ ├── ros2-canopen-logo.png
│ └── system-interface.png
│ ├── index.rst
│ ├── make.bat
│ ├── quickstart
│ ├── examples.rst
│ ├── installation.rst
│ └── operation.rst
│ ├── software-tests
│ ├── proxy-driver-test.rst
│ └── ros2_control_system-test.rst
│ └── user-guide
│ ├── cia402-driver.rst
│ ├── configuration.rst
│ ├── how-to-create-a-cia301-system.rst
│ ├── how-to-create-a-configuration.rst
│ ├── how-to-create-a-robot-system.rst
│ ├── master.rst
│ ├── operation.rst
│ ├── operation
│ ├── managed-service-interface.rst
│ ├── ros2-control-interface.rst
│ └── service-interface.rst
│ └── proxy-driver.rst
├── canopen_402_driver
├── CHANGELOG.rst
├── CMakeLists.txt
├── LICENSE
├── include
│ └── canopen_402_driver
│ │ ├── base.hpp
│ │ ├── cia402_driver.hpp
│ │ ├── command.hpp
│ │ ├── default_homing_mode.hpp
│ │ ├── homing_mode.hpp
│ │ ├── lifecycle_cia402_driver.hpp
│ │ ├── mode.hpp
│ │ ├── mode_forward_helper.hpp
│ │ ├── mode_target_helper.hpp
│ │ ├── motor.hpp
│ │ ├── node_interfaces
│ │ ├── node_canopen_402_driver.hpp
│ │ └── node_canopen_402_driver_impl.hpp
│ │ ├── profiled_position_mode.hpp
│ │ ├── state.hpp
│ │ ├── visibility_control.h
│ │ └── word_accessor.hpp
├── package.xml
├── src
│ ├── cia402_driver.cpp
│ ├── command.cpp
│ ├── default_homing_mode.cpp
│ ├── lifecycle_cia402_driver.cpp
│ ├── motor.cpp
│ ├── node_interfaces
│ │ └── node_canopen_402_driver.cpp
│ └── state.cpp
└── test
│ ├── CMakeLists.txt
│ ├── master.dcf
│ └── test_driver_component.cpp
├── canopen_base_driver
├── CHANGELOG.rst
├── CMakeLists.txt
├── LICENSE
├── include
│ └── canopen_base_driver
│ │ ├── base_driver.hpp
│ │ ├── diagnostic_collector.hpp
│ │ ├── lely_driver_bridge.hpp
│ │ ├── lifecycle_base_driver.hpp
│ │ ├── node_interfaces
│ │ ├── node_canopen_base_driver.hpp
│ │ └── node_canopen_base_driver_impl.hpp
│ │ └── visibility_control.h
├── package.xml
├── src
│ ├── base_driver.cpp
│ ├── lely_driver_bridge.cpp
│ ├── lifecycle_base_driver.cpp
│ └── node_interfaces
│ │ └── node_canopen_base_driver.cpp
└── test
│ ├── CMakeLists.txt
│ ├── master.dcf
│ ├── test_base_driver_component.cpp
│ └── test_node_canopen_base_driver_ros.cpp
├── canopen_core
├── CHANGELOG.rst
├── CMakeLists.txt
├── ConfigExtras.cmake
├── LICENSE
├── include
│ └── canopen_core
│ │ ├── configuration_manager.hpp
│ │ ├── device_container.hpp
│ │ ├── device_container_error.hpp
│ │ ├── driver_error.hpp
│ │ ├── driver_node.hpp
│ │ ├── exchange.hpp
│ │ ├── lifecycle_manager.hpp
│ │ ├── master_error.hpp
│ │ ├── master_node.hpp
│ │ ├── node_interfaces
│ │ ├── node_canopen_driver.hpp
│ │ ├── node_canopen_driver_interface.hpp
│ │ ├── node_canopen_master.hpp
│ │ └── node_canopen_master_interface.hpp
│ │ └── visibility_control.h
├── launch
│ └── canopen.launch.py
├── package.xml
├── readme.md
├── scripts
│ └── setup_vcan.sh
├── src
│ ├── configuration_manager.cpp
│ ├── device_container.cpp
│ ├── device_container_error.cpp
│ ├── device_container_node.cpp
│ ├── driver_error.cpp
│ ├── driver_node.cpp
│ ├── lifecycle_manager.cpp
│ ├── master_error.cpp
│ ├── master_node.cpp
│ └── node_interfaces
│ │ ├── node_canopen_driver.cpp
│ │ └── node_canopen_master.cpp
└── test
│ ├── CMakeLists.txt
│ ├── bus_configs
│ ├── bad_driver_duplicate.yml
│ ├── bad_driver_no_driver.yml
│ ├── bad_driver_no_id.yml
│ ├── bad_driver_no_package.yml
│ ├── bad_master_no_driver.yml
│ ├── bad_master_no_id.yml
│ ├── bad_master_no_package.yml
│ ├── bad_no_master.yml
│ ├── good_driver.yml
│ ├── good_master.yml
│ └── good_master_and_two_driver.yml
│ ├── master.dcf
│ ├── simple.eds
│ ├── test_canopen_driver.cpp
│ ├── test_canopen_master.cpp
│ ├── test_device_container.cpp
│ ├── test_errors.cpp
│ ├── test_lifecycle_canopen_driver.cpp
│ ├── test_lifecycle_canopen_master.cpp
│ ├── test_lifecycle_manager.cpp
│ ├── test_node_canopen_driver.cpp
│ └── test_node_canopen_master.cpp
├── canopen_fake_slaves
├── CHANGELOG.rst
├── CMakeLists.txt
├── LICENSE
├── Readme.md
├── config
│ ├── cia402_slave.eds
│ └── simple_slave.eds
├── include
│ └── canopen_fake_slaves
│ │ ├── base_slave.hpp
│ │ ├── basic_slave.hpp
│ │ ├── cia402_slave.hpp
│ │ └── motion_generator.hpp
├── launch
│ ├── basic_slave.launch.py
│ └── cia402_slave.launch.py
├── package.xml
└── src
│ ├── basic_slave.cpp
│ ├── cia402_slave.cpp
│ └── motion_generator.cpp
├── canopen_interfaces
├── CHANGELOG.rst
├── CMakeLists.txt
├── LICENSE
├── msg
│ └── COData.msg
├── package.xml
└── srv
│ ├── COHeartbeatID.srv
│ ├── CONmtID.srv
│ ├── CONode.srv
│ ├── CORead.srv
│ ├── COReadID.srv
│ ├── COTargetDouble.srv
│ ├── COWrite.srv
│ └── COWriteID.srv
├── canopen_master_driver
├── CHANGELOG.rst
├── CMakeLists.txt
├── LICENSE
├── include
│ └── canopen_master_driver
│ │ ├── lely_master_bridge.hpp
│ │ ├── lifecycle_master_driver.hpp
│ │ ├── master_driver.hpp
│ │ ├── node_interfaces
│ │ ├── node_canopen_basic_master.hpp
│ │ └── node_canopen_basic_master_impl.hpp
│ │ └── visibility_control.h
├── package.xml
├── src
│ ├── lely_master_bridge.cpp
│ ├── lifecycle_master_driver.cpp
│ ├── master_driver.cpp
│ └── node_interfaces
│ │ └── node_canopen_basic_master.cpp
└── test
│ ├── CMakeLists.txt
│ ├── master.dcf
│ ├── test_master_driver_component.cpp
│ ├── test_node_canopen_basic_master.cpp
│ └── test_node_canopen_basic_master_ros.cpp
├── canopen_proxy_driver
├── CHANGELOG.rst
├── CMakeLists.txt
├── LICENSE
├── config
│ ├── concurrency_test
│ │ └── master.dcf
│ ├── nmt_test
│ │ └── master.dcf
│ ├── pdo_test
│ │ └── master.dcf
│ └── sdo_test
│ │ └── master.dcf
├── include
│ └── canopen_proxy_driver
│ │ ├── lifecycle_proxy_driver.hpp
│ │ ├── node_interfaces
│ │ ├── node_canopen_proxy_driver.hpp
│ │ └── node_canopen_proxy_driver_impl.hpp
│ │ ├── proxy_driver.hpp
│ │ └── visibility_control.h
├── package.xml
├── readme.md
├── src
│ ├── lifecycle_proxy_driver.cpp
│ ├── node_interfaces
│ │ └── node_canopen_proxy_driver.cpp
│ └── proxy_driver.cpp
└── test
│ ├── CMakeLists.txt
│ ├── master.dcf
│ ├── test_driver_component.cpp
│ └── test_node_interface.cpp
├── canopen_ros2_control
├── CHANGELOG.rst
├── CMakeLists.txt
├── LICENSE
├── canopen_ros2_control.xml
├── include
│ └── canopen_ros2_control
│ │ ├── canopen_system.hpp
│ │ ├── cia402_data.hpp
│ │ ├── cia402_system.hpp
│ │ ├── helpers.hpp
│ │ ├── robot_system.hpp
│ │ └── visibility_control.h
├── package.xml
├── src
│ ├── canopen_system.cpp
│ ├── cia402_system.cpp
│ └── robot_system.cpp
└── test
│ └── test_canopen_system.cpp
├── canopen_ros2_controllers
├── CHANGELOG.rst
├── CMakeLists.txt
├── LICENSE
├── canopen_ros2_controllers.xml
├── include
│ └── canopen_ros2_controllers
│ │ ├── canopen_proxy_controller.hpp
│ │ ├── cia402_device_controller.hpp
│ │ └── visibility_control.h
├── package.xml
├── src
│ ├── canopen_proxy_controller.cpp
│ └── cia402_device_controller.cpp
└── test
│ ├── test_canopen_proxy_controller.cpp
│ ├── test_canopen_proxy_controller.hpp
│ ├── test_load_canopen_proxy_controller.cpp
│ ├── test_load_cia402_device_controller.cpp
│ └── test_load_cia402_robot_controller.cpp
├── canopen_tests
├── CHANGELOG.rst
├── CMakeLists.txt
├── LICENSE
├── README.md
├── ROS_NAMESPACES.md
├── config
│ ├── canopen_system
│ │ ├── bus.yml
│ │ ├── ros2_controllers.yaml
│ │ └── simple.eds
│ ├── cia402
│ │ ├── bus.yml
│ │ └── cia402_slave.eds
│ ├── cia402_diagnostics
│ │ ├── bus.yml
│ │ └── cia402_slave.eds
│ ├── cia402_lifecycle
│ │ ├── bus.yml
│ │ └── cia402_slave.eds
│ ├── cia402_namespaced_system
│ │ ├── bus.yml
│ │ ├── cia402_slave.eds
│ │ └── ros2_controllers.yaml
│ ├── cia402_system
│ │ ├── bus.yml
│ │ ├── cia402_slave.eds
│ │ └── ros2_controllers.yaml
│ ├── robot_control
│ │ ├── bus.yml
│ │ ├── cia402_slave.eds
│ │ ├── prbt_0_1.dcf
│ │ └── ros2_controllers.yaml
│ ├── simple
│ │ ├── bus.yml
│ │ └── simple.eds
│ ├── simple_diagnostics
│ │ ├── bus.yml
│ │ └── simple.eds
│ └── simple_lifecycle
│ │ ├── bus.yml
│ │ └── simple.eds
├── launch
│ ├── analyzers
│ │ ├── cia402_diagnostic_analyzer.yaml
│ │ └── proxy_diagnostic_analyzer.yaml
│ ├── canopen_system.launch.py
│ ├── cia402_diagnostics_setup.launch.py
│ ├── cia402_lifecycle_setup.launch.py
│ ├── cia402_namespaced_system.launch.py
│ ├── cia402_setup.launch.py
│ ├── cia402_system.launch.py
│ ├── proxy_diagnostics_setup.launch.py
│ ├── proxy_lifecycle_setup.launch.py
│ ├── proxy_setup.launch.py
│ ├── proxy_setup_namespaced.launch.py
│ ├── robot_control_setup.launch.py
│ └── view_urdf.launch.py
├── launch_tests
│ ├── test_cia402_driver.py
│ ├── test_proxy_driver.py
│ ├── test_proxy_driver_namespaced.py
│ ├── test_proxy_lifecycle_driver.py
│ └── test_robot_control.py
├── package.xml
├── rviz
│ └── robot_controller.rviz
└── urdf
│ ├── canopen_system
│ ├── canopen_system.ros2_control.xacro
│ └── canopen_system.urdf.xacro
│ ├── cia402_system
│ ├── cia402_system.ros2_control.xacro
│ └── cia402_system.urdf.xacro
│ └── robot_controller
│ ├── robot_controller.macro.xacro
│ ├── robot_controller.ros2_control.xacro
│ └── robot_controller.urdf.xacro
├── canopen_utils
├── CHANGELOG.rst
├── LICENSE
├── canopen_utils
│ ├── __init__.py
│ ├── cyclic_tester.py
│ ├── launch_test_node.py
│ ├── simple_rpdo_tpdo_tester.py
│ └── test_node.py
├── no_tests
│ ├── _test_copyright.py
│ ├── _test_flake8.py
│ └── _test_pep257.py
├── package.xml
├── resource
│ └── canopen_utils
├── setup.cfg
└── setup.py
└── lely_core_libraries
├── CHANGELOG.rst
├── CMakeLists.txt
├── LICENSE
├── cmake
└── lely_core_libraries-extras.cmake
├── cogen
├── __init__.py
└── cogen.py
├── package.xml
├── patches
└── 0001-Fix-dcf-tools.patch
└── setup.cfg
/.clang-format:
--------------------------------------------------------------------------------
1 | ---
2 | Language: Cpp
3 | BasedOnStyle: Google
4 |
5 | AccessModifierOffset: -2
6 | AlignAfterOpenBracket: AlwaysBreak
7 | BreakBeforeBraces: Allman
8 | ColumnLimit: 100
9 | ConstructorInitializerIndentWidth: 0
10 | ContinuationIndentWidth: 2
11 | IndentWidth: 2
12 | TabWidth: 2
13 | DerivePointerAlignment: false
14 | PointerAlignment: Middle
15 | ReflowComments: true
16 | IncludeBlocks: Preserve
17 | ...
18 |
--------------------------------------------------------------------------------
/.codespellignore:
--------------------------------------------------------------------------------
1 | ons
2 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: bug
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior
15 |
16 | **Expected behavior**
17 | A clear and concise description of what you expected to happen.
18 |
19 | **Logs**
20 |
21 | **Setup:**
22 | - Device:
23 | - OS:
24 | - ROS-Distro:
25 | - Branch/Commit:
26 |
27 | **Additional context**
28 | Add any other context about the problem here.
29 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: enhancement
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/question.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Question
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: question
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **Logs**
14 | Add build or execution log for context.
15 |
16 | **Setup:**
17 | - Device:
18 | - OS:
19 | - ROS-Distro:
20 | - Branch/Commit:
21 |
22 | **Additional context**
23 | Add any other context about the problem here.
24 |
--------------------------------------------------------------------------------
/.github/dependabot.yaml:
--------------------------------------------------------------------------------
1 | # Set update schedule for GitHub Actions
2 |
3 | version: 2
4 | updates:
5 |
6 | - package-ecosystem: "github-actions"
7 | directory: "/"
8 | schedule:
9 | # Check for updates to GitHub Actions every week
10 | interval: "weekly"
11 |
--------------------------------------------------------------------------------
/.github/workflows/ci-format.yml:
--------------------------------------------------------------------------------
1 | # This is a format job. Pre-commit has a first-party GitHub action, so we use
2 | # that: https://github.com/pre-commit/action
3 |
4 | name: Pre-commit Format
5 |
6 | on:
7 | workflow_dispatch:
8 | pull_request:
9 |
10 | jobs:
11 | pre-commit:
12 | name: Format
13 | runs-on: ubuntu-22.04
14 | steps:
15 | - uses: actions/checkout@v4
16 | - uses: actions/setup-python@v5
17 | with:
18 | python-version: 3.10.6
19 | - name: Install system hooks
20 | run: sudo apt update && sudo apt install -qq clang-format-14 cppcheck
21 | - uses: pre-commit/action@v3.0.1
22 | with:
23 | extra_args: --all-files --hook-stage manual
24 |
--------------------------------------------------------------------------------
/.github/workflows/ci-ros-lint.yml.backup:
--------------------------------------------------------------------------------
1 | name: ROS Lint
2 | on:
3 | pull_request:
4 |
5 | jobs:
6 | ament_lint:
7 | name: ament_${{ matrix.linter }}
8 | runs-on: ubuntu-20.04
9 | strategy:
10 | fail-fast: false
11 | matrix:
12 | linter: [cppcheck, copyright, lint_cmake]
13 | steps:
14 | - uses: actions/checkout@v3
15 | - uses: ros-tooling/setup-ros@v0.2
16 | - uses: ros-tooling/action-ros-lint@v0.1
17 | with:
18 | distribution: rolling
19 | linter: ${{ matrix.linter }}
20 | package-name:
21 | $PKG_NAME$
22 |
23 | ament_lint_100:
24 | name: ament_${{ matrix.linter }}
25 | runs-on: ubuntu-20.04
26 | strategy:
27 | fail-fast: false
28 | matrix:
29 | linter: [cpplint]
30 | steps:
31 | - uses: actions/checkout@v3
32 | - uses: ros-tooling/setup-ros@v0.2
33 | - uses: ros-tooling/action-ros-lint@v0.1
34 | with:
35 | distribution: rolling
36 | linter: cpplint
37 | arguments: "--linelength=100 --filter=-whitespace/newline"
38 | package-name:
39 | ros2_canopen
40 |
--------------------------------------------------------------------------------
/.github/workflows/docker.yml:
--------------------------------------------------------------------------------
1 | name: Create and publish a Docker image
2 | on:
3 | push:
4 | branches: ['master']
5 | workflow_dispatch:
6 |
7 | env:
8 | REGISTRY: ghcr.io
9 | IMAGE_NAME: ${{ github.repository }}
10 |
11 | jobs:
12 | build-and-push-image:
13 | runs-on: ubuntu-22.04
14 |
15 | permissions:
16 | contents: read
17 | packages: write
18 |
19 | steps:
20 | - name: Checkout repository
21 | uses: actions/checkout@v4
22 | - name: Log in to the Container registry
23 | uses: docker/login-action@v3
24 | with:
25 | registry: ${{ env.REGISTRY }}
26 | username: ${{ github.actor }}
27 | password: ${{ secrets.GITHUB_TOKEN }}
28 |
29 | - name: Extract metadata (tags, labels) for Docker
30 | id: meta
31 | uses: docker/metadata-action@v5
32 | with:
33 | images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
34 |
35 | - name: Build and push Docker image
36 | uses: docker/build-push-action@v6
37 | with:
38 | context: .
39 | push: true
40 | tags: ${{ steps.meta.outputs.tags }}
41 | labels: ${{ steps.meta.outputs.labels }}
42 |
--------------------------------------------------------------------------------
/.github/workflows/humble.yml:
--------------------------------------------------------------------------------
1 | name: Industrial CI Humble
2 |
3 | on:
4 | push:
5 | branches: [ humble ]
6 | pull_request:
7 | branches: [ humble ]
8 | workflow_dispatch:
9 |
10 | jobs:
11 | industrial_ci:
12 | name: ROS ${{ matrix.ROS_DISTRO }} (${{ matrix.ROS_REPO }})
13 | runs-on: ubuntu-22.04
14 | strategy:
15 | fail-fast: false
16 | matrix:
17 | ROS_DISTRO: [humble]
18 | ROS_REPO: [testing]
19 | env:
20 | CCACHE_DIR: "${{ github.workspace }}/.ccache"
21 | steps:
22 | - uses: actions/checkout@v4
23 | - uses: actions/cache@v4
24 | with:
25 | path: ${{ env.CCACHE_DIR }}
26 | key: ccache-${{ matrix.ROS_DISTRO }}-${{ matrix.ROS_REPO }}-${{github.run_id}}
27 | restore-keys: |
28 | ccache-${{ matrix.ROS_DISTRO }}-${{ matrix.ROS_REPO }}-
29 | - uses: 'ros-industrial/industrial_ci@master'
30 | env:
31 | BEFORE_INSTALL_TARGET_DEPENDENCIES: 'sudo apt-get update'
32 | ROS_DISTRO: ${{ matrix.ROS_DISTRO }}
33 | ROS_REPO: ${{ matrix.ROS_REPO }}
34 |
--------------------------------------------------------------------------------
/.github/workflows/humble_documentation.yml:
--------------------------------------------------------------------------------
1 | name: Documentation Humble
2 |
3 | # Controls when the workflow will run
4 | on:
5 | # Triggers the workflow on push or pull request events but only for the master branch
6 | push:
7 | branches: [ humble ]
8 |
9 | # Allows you to run this workflow manually from the Actions tab
10 | workflow_dispatch:
11 |
12 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel
13 | jobs:
14 | # This workflow contains a single job called "build"
15 | build_documentation:
16 | # The type of runner that the job will run on
17 | runs-on: ubuntu-22.04
18 |
19 | # Steps represent a sequence of tasks that will be executed as part of the job
20 | steps:
21 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
22 | - uses: actions/checkout@v4
23 |
24 | - name: Install dependencies
25 | run: |
26 | sudo apt-get update -qq
27 | sudo apt-get install -y -qq doxygen graphviz plantuml
28 | pip install sphinx-rtd-theme
29 | pip install sphinxcontrib-plantuml
30 | pip install sphinx-mdinclude
31 | pip install breathe
32 | pip install exhale
33 |
34 | - name: Build doxygen
35 | run: |
36 | cd ./canopen/doxygen/
37 | doxygen
38 | cd ../..
39 |
40 | - name: Build documentation
41 | run: |
42 | cd ./canopen/sphinx/
43 | make html
44 | cd ../..
45 |
46 | - name: Create commit
47 | run: |
48 | git clone https://github.com/ros-industrial/ros2_canopen.git --branch gh-pages --single-branch gh-pages
49 | mkdir -p gh-pages/manual/humble/
50 | mkdir -p gh-pages/api/humble/
51 | cp -r ./canopen/sphinx/_build/html/* gh-pages/manual/humble/
52 | cp -r ./canopen/doxygen/_build/html/* gh-pages/api/humble/
53 | cd gh-pages
54 | git config --local user.email "action@github.com"
55 | git config --local user.name "GitHub Action"
56 | git add .
57 | git commit -m "Update documentation" -a || true
58 |
59 | - name: Push changes
60 | uses: ad-m/github-push-action@master
61 | with:
62 | branch: gh-pages
63 | directory: gh-pages
64 | github_token: ${{ secrets.GITHUB_TOKEN }}
65 |
--------------------------------------------------------------------------------
/.github/workflows/iron.yml:
--------------------------------------------------------------------------------
1 | name: Industiral CI Iron
2 |
3 | on:
4 | push:
5 | branches: [ iron ]
6 | pull_request:
7 | branches: [ iron ]
8 | workflow_dispatch:
9 |
10 | jobs:
11 | industrial_ci:
12 | name: ROS ${{ matrix.ROS_DISTRO }} (${{ matrix.ROS_REPO }})
13 | runs-on: ubuntu-22.04
14 | strategy:
15 | fail-fast: false
16 | matrix:
17 | ROS_DISTRO: [iron]
18 | ROS_REPO: [testing]
19 | env:
20 | CCACHE_DIR: "${{ github.workspace }}/.ccache"
21 | steps:
22 | - uses: actions/checkout@v4
23 | - uses: actions/cache@v4
24 | with:
25 | path: ${{ env.CCACHE_DIR }}
26 | key: ccache-${{ matrix.ROS_DISTRO }}-${{ matrix.ROS_REPO }}-${{github.run_id}}
27 | restore-keys: |
28 | ccache-${{ matrix.ROS_DISTRO }}-${{ matrix.ROS_REPO }}-
29 | - uses: 'ros-industrial/industrial_ci@master'
30 | env:
31 | BEFORE_INSTALL_TARGET_DEPENDENCIES: 'sudo apt-get update'
32 | ROS_DISTRO: ${{ matrix.ROS_DISTRO }}
33 | ROS_REPO: ${{ matrix.ROS_REPO }}
34 | NOT_TEST_BUILD: 1
35 |
--------------------------------------------------------------------------------
/.github/workflows/iron_documentation.yml:
--------------------------------------------------------------------------------
1 | name: Documentation Iron
2 |
3 | # Controls when the workflow will run
4 | on:
5 | # Triggers the workflow on push or pull request events but only for the master branch
6 | push:
7 | branches: [ iron ]
8 |
9 | # Allows you to run this workflow manually from the Actions tab
10 | workflow_dispatch:
11 |
12 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel
13 | jobs:
14 | # This workflow contains a single job called "build"
15 | build_documentation:
16 | # The type of runner that the job will run on
17 | runs-on: ubuntu-22.04
18 |
19 | # Steps represent a sequence of tasks that will be executed as part of the job
20 | steps:
21 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
22 | - uses: actions/checkout@v4
23 |
24 | - name: Install dependencies
25 | run: |
26 | sudo apt-get update -qq
27 | sudo apt-get install -y -qq doxygen graphviz plantuml
28 | pip install sphinx-rtd-theme
29 | pip install sphinxcontrib-plantuml
30 | pip install sphinx-mdinclude
31 | pip install breathe
32 | pip install exhale
33 |
34 | - name: Build doxygen
35 | run: |
36 | cd ./canopen/doxygen/
37 | doxygen
38 | cd ../..
39 |
40 | - name: Build documentation
41 | run: |
42 | cd ./canopen/sphinx/
43 | make html
44 | cd ../..
45 |
46 | - name: Create commit
47 | run: |
48 | git clone https://github.com/ros-industrial/ros2_canopen.git --branch gh-pages --single-branch gh-pages
49 | mkdir -p gh-pages/manual/iron/
50 | mkdir -p gh-pages/api/iron/
51 | cp -r ./canopen/sphinx/_build/html/* gh-pages/manual/iron/
52 | cp -r ./canopen/doxygen/_build/html/* gh-pages/api/iron/
53 | cd gh-pages
54 | git config --local user.email "action@github.com"
55 | git config --local user.name "GitHub Action"
56 | git add .
57 | git commit -m "Update documentation" -a || true
58 |
59 | - name: Push changes
60 | uses: ad-m/github-push-action@master
61 | with:
62 | branch: gh-pages
63 | directory: gh-pages
64 | github_token: ${{ secrets.GITHUB_TOKEN }}
65 |
--------------------------------------------------------------------------------
/.github/workflows/prerelease-rolling.yml:
--------------------------------------------------------------------------------
1 | name: Prerelease-Test Rolling
2 |
3 | on:
4 | workflow_dispatch:
5 | push:
6 | tags:
7 | - "*"
8 |
9 | jobs:
10 | industrial_ci:
11 | name: ROS ${{ matrix.ROS_DISTRO }} (${{ matrix.ROS_REPO }})
12 | runs-on: ubuntu-22.04
13 | strategy:
14 | fail-fast: false
15 | matrix:
16 | ROS_DISTRO: [rolling]
17 | ROS_REPO: [testing]
18 | steps:
19 | - uses: actions/checkout@v4
20 | - uses: 'ros-industrial/industrial_ci@master'
21 | env:
22 | BEFORE_INSTALL_TARGET_DEPENDENCIES: 'sudo apt-get update'
23 | AFTER_BUILD_TARGET_WORKSPACE: 'set +u && COLCON_TRACE=0 AMENT_TRACE_SETUP_FILES=0 source /root/target_ws/install/setup.bash && set -u'
24 | ROS_DISTRO: ${{ matrix.ROS_DISTRO }}
25 | ROS_REPO: ${{ matrix.ROS_REPO }}
26 | PRERELEASE: true
27 |
--------------------------------------------------------------------------------
/.github/workflows/rolling.yml:
--------------------------------------------------------------------------------
1 | name: Industrial CI Rolling
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 | workflow_dispatch:
9 |
10 | jobs:
11 | industrial_ci:
12 | name: ROS ${{ matrix.ROS_DISTRO }} (${{ matrix.ROS_REPO }})
13 | runs-on: ubuntu-22.04
14 | strategy:
15 | fail-fast: false
16 | matrix:
17 | ROS_DISTRO: [rolling]
18 | ROS_REPO: [testing]
19 | env:
20 | CCACHE_DIR: "${{ github.workspace }}/.ccache"
21 | steps:
22 | - uses: actions/checkout@v4
23 | - uses: actions/cache@v4
24 | with:
25 | path: ${{ env.CCACHE_DIR }}
26 | key: ccache-${{ matrix.ROS_DISTRO }}-${{ matrix.ROS_REPO }}-${{github.run_id}}
27 | restore-keys: |
28 | ccache-${{ matrix.ROS_DISTRO }}-${{ matrix.ROS_REPO }}-
29 | - uses: 'ros-industrial/industrial_ci@master'
30 | env:
31 | BEFORE_INSTALL_TARGET_DEPENDENCIES: 'sudo apt-get update'
32 | AFTER_BUILD_TARGET_WORKSPACE: 'set +u && COLCON_TRACE=0 AMENT_TRACE_SETUP_FILES=0 source /root/target_ws/install/setup.bash && set -u'
33 | ROS_DISTRO: ${{ matrix.ROS_DISTRO }}
34 | ROS_REPO: ${{ matrix.ROS_REPO }}
35 | PRERELEASE: false
36 |
--------------------------------------------------------------------------------
/.github/workflows/rolling_documentation.yml:
--------------------------------------------------------------------------------
1 | name: Documentation Rolling
2 |
3 | # Controls when the workflow will run
4 | on:
5 | # Triggers the workflow on push or pull request events but only for the master branch
6 | push:
7 | branches: [ master ]
8 |
9 | # Allows you to run this workflow manually from the Actions tab
10 | workflow_dispatch:
11 |
12 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel
13 | jobs:
14 | # This workflow contains a single job called "build"
15 | build_documentation:
16 | # The type of runner that the job will run on
17 | runs-on: ubuntu-22.04
18 |
19 | # Steps represent a sequence of tasks that will be executed as part of the job
20 | steps:
21 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
22 | - uses: actions/checkout@v4
23 |
24 | - name: Install dependencies
25 | run: |
26 | sudo apt-get update -qq
27 | sudo apt-get install -y -qq doxygen graphviz plantuml
28 | pip install sphinx-rtd-theme
29 | pip install sphinxcontrib-plantuml
30 | pip install sphinx-mdinclude
31 | pip install breathe
32 | pip install exhale
33 |
34 | - name: Build doxygen
35 | run: |
36 | cd ./canopen/doxygen/
37 | doxygen
38 | cd ../..
39 |
40 | - name: Build documentation
41 | run: |
42 | cd ./canopen/sphinx/
43 | make html
44 | cd ../..
45 |
46 | - name: Create commit
47 | run: |
48 | git clone https://github.com/ros-industrial/ros2_canopen.git --branch gh-pages --single-branch gh-pages
49 | mkdir -p gh-pages/manual/rolling/
50 | mkdir -p gh-pages/api/rolling/
51 | cp -r ./canopen/sphinx/_build/html/* gh-pages/manual/rolling/
52 | cp -r ./canopen/doxygen/_build/html/* gh-pages/api/rolling/
53 | cd gh-pages
54 | git config --local user.email "action@github.com"
55 | git config --local user.name "GitHub Action"
56 | git add .
57 | git commit -m "Update documentation" -a || true
58 |
59 | - name: Push changes
60 | uses: ad-m/github-push-action@master
61 | with:
62 | branch: gh-pages
63 | directory: gh-pages
64 | github_token: ${{ secrets.GITHUB_TOKEN }}
65 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode/
2 | **/doc_output/
3 | **/__pycache__/
4 | **/_build
5 | **/api
6 |
--------------------------------------------------------------------------------
/.gitlab-ci.yml:
--------------------------------------------------------------------------------
1 | stages:
2 | - doc
3 | - build
4 | - dockerize
5 |
6 | doxygen:
7 | stage: doc
8 | image: ubuntu:latest
9 | before_script:
10 | - apt-get update -qq
11 | - apt-get install -y -qq doxygen graphviz
12 | script:
13 | - cd canopen/doxygen && doxygen
14 | artifacts:
15 | paths:
16 | - canopen/doxygen/doc_output/
17 | tags:
18 | - asprunner
19 |
20 | sphinx:
21 | stage: doc
22 | image: sphinxdoc/sphinx:latest
23 | before_script:
24 | - apt-get update -qq
25 | - apt-get install -y -qq doxygen graphviz
26 | - pip install sphinx-rtd-theme
27 | - pip install sphinx-mdinclude
28 | - pip install breathe
29 | - pip install exhale
30 | script:
31 | - cd canopen/sphinx/
32 | - make html
33 | artifacts:
34 | name: documentation
35 | paths:
36 | - canopen/sphinx/_build
37 | tags:
38 | - asprunner
39 |
40 |
41 | .build:
42 | stage: build
43 | before_script:
44 | - apt-get update -qq
45 | - apt-get install -y -qq git-core
46 | - git clone --quiet --depth 1 https://github.com/ros-industrial/industrial_ci .industrial_ci
47 | script: .industrial_ci/gitlab.sh
48 | services: []
49 | variables:
50 | ISOLATION: shell
51 | tags:
52 | - asprunner
53 |
54 | galactic:
55 | extends: [.build]
56 | image: ros:galactic
57 |
58 | foxy:
59 | extends: [.build]
60 | image: ros:foxy
61 |
62 |
63 | dockerize-job:
64 | stage: dockerize
65 | image: docker:19.03.12
66 | services:
67 | - docker:19.03.12-dind
68 | variables:
69 | DOCKER_DRIVER: overlay2
70 | DOCKER_HOST: tcp://docker:2375
71 | DOCKER_TLS_CERTDIR: ""
72 | IMAGE_TAG: $CI_REGISTRY_IMAGE/ros2_canopen:$CI_COMMIT_REF_SLUG
73 | IMAGE_TAG_LATEST: $CI_REGISTRY_IMAGE/ros2_canopen:latest
74 | before_script:
75 | - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
76 | - docker info
77 | script:
78 | - docker pull IMAGE_TAG_LATEST || true
79 | - docker build --cache-from IMAGE_TAG_LATEST --tag $IMAGE_TAG --tag $IMAGE_TAG_LATEST .
80 | - docker push $IMAGE_TAG
81 | - docker push $IMAGE_TAG_LATEST
82 | tags:
83 | - docker-build
84 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ros:rolling-ros-core
2 |
3 |
4 | RUN apt-get update \
5 | && apt-get install -y \
6 | python3-rosdep \
7 | python3-argcomplete \
8 | python3-colcon-common-extensions \
9 | build-essential \
10 | pkg-config \
11 | python3-wheel
12 |
13 | WORKDIR /home/can_ws/src
14 | COPY . ros2_canopen
15 |
16 | WORKDIR /home/can_ws/
17 | RUN . /opt/ros/rolling/setup.sh \
18 | && rosdep init && rosdep update \
19 | && rosdep install --from-paths src --ignore-src -r -y \
20 | && colcon build \
21 | && . install/setup.sh
22 |
--------------------------------------------------------------------------------
/canopen/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.8)
2 | project(canopen NONE)
3 | find_package(ament_cmake REQUIRED)
4 | ament_package()
5 |
--------------------------------------------------------------------------------
/canopen/doxygen/Doxyfile:
--------------------------------------------------------------------------------
1 | # All settings not listed here will use the Doxygen default values.
2 |
3 | PROJECT_NAME = "ros2_canopen"
4 | PROJECT_NUMBER = master
5 | PROJECT_BRIEF = "C++ ROS CANopen Library"
6 |
7 | # Use these lines to include the generated logging.hpp (update install path if needed)
8 | INPUT = ../../canopen_core/include ../../canopen_base_driver/include ../../canopen_402_driver/include ../../canopen_proxy_driver/include
9 |
10 | RECURSIVE = YES
11 | OUTPUT_DIRECTORY = _build
12 |
13 | EXTRACT_ALL = YES
14 | SORT_MEMBER_DOCS = NO
15 |
16 | GENERATE_LATEX = NO
17 | GENERATE_XML = YES
18 |
19 | ENABLE_PREPROCESSING = YES
20 |
21 | DOT_GRAPH_MAX_NODES = 101
22 |
23 | FILE_PATTERNS = *.cpp *.h *.hpp *.md
24 |
--------------------------------------------------------------------------------
/canopen/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | canopen
5 | 0.3.0
6 | Meta-package aggregating the ros2_canopen packages and documentation
7 | Christoph Hellmann Santos
8 | Vishnuprasad Prachandabhanu
9 | Apache-2.0
10 |
11 | ament_cmake
12 | canopen_interfaces
13 | canopen_core
14 | canopen_base_driver
15 | lely_core_libraries
16 | canopen_proxy_driver
17 | canopen_base_driver
18 | canopen_402_driver
19 |
20 |
21 | ament_cmake
22 |
23 |
24 |
--------------------------------------------------------------------------------
/canopen/sphinx/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line, and also
5 | # from the environment for the first two.
6 | SPHINXOPTS ?=
7 | SPHINXBUILD ?= sphinx-build
8 | SOURCEDIR = .
9 | BUILDDIR = _build
10 |
11 | # Put it first so that "make" without argument is like "make help".
12 | help:
13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14 |
15 | .PHONY: help Makefile clean
16 |
17 | clean:
18 | rm -rf "_doxygen/" "api/"
19 | @$(SPHINXBUILD) -M clean "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
20 |
21 | # Catch-all target: route all unknown targets to Sphinx using the new
22 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
23 | %: Makefile
24 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
25 |
--------------------------------------------------------------------------------
/canopen/sphinx/_static/css/custom.css:
--------------------------------------------------------------------------------
1 |
2 | .wy-table-responsive table td,
3 | .wy-table-responsive table th {
4 | white-space:normal;
5 | }
6 |
7 | tr {
8 | white-space: normal;
9 | }
10 |
11 | thead {
12 | white-space: normal;
13 | }
14 |
15 | table {
16 | white-space: normal;
17 | }
18 |
--------------------------------------------------------------------------------
/canopen/sphinx/developers-guide/design-objectives.rst:
--------------------------------------------------------------------------------
1 | Design Objectives
2 | ======================
3 |
4 | The ros_canopen stack had a number of drawbacks especially when it came
5 | to maintainablity and complexity. In order to address these drawbacks, we
6 | have decided to redesign the ros2_canopen stack completely with the following
7 | development goals.
8 |
9 |
10 | .. csv-table:: Development Objectives
11 | :header-rows: 1
12 | :class: longtable
13 | :delim: ;
14 | :widths: 1 2
15 |
16 | Objective; Description
17 | Understandability and Extendability; One major drawback of ros_canopen was that actually extending it with new drivers required to understand the complex stack with its different layers.
18 | Robust Parallel Requests; When multiple nodes are running on the same bus, it should be possible to make requests to the nodes concurrently from ROS2 and have the canopen master handle the sequencing.
19 | Easy Maintenance; Maintenance effort should be reduced as much as possible. Therefore, a clean and clear code structure and documentation is needed and only funcitonalities that are not already available from other high quality open source libraries should be self implemented.
20 | Enable controlling drives via ros2_control; A driver for CIA402 and a ros2_control interface need to be developed.
21 | Enable controlling drives via ros2 ervice interface; A driver for CIA402 and a service interface need to be developed.
22 | Enable proxy functionalities via ros2 interface; For debugging purposes a proxy driver should be developed, which enables sending and receiving CANopen objects via a ros2 interface.
23 | Good enough documentation; Write documentation for using and understanding the ros2_canopen stack.
24 |
--------------------------------------------------------------------------------
/canopen/sphinx/developers-guide/new-device-manager.rst:
--------------------------------------------------------------------------------
1 | Creating your device manager
2 | ============================
3 |
--------------------------------------------------------------------------------
/canopen/sphinx/developers-guide/new-master.rst:
--------------------------------------------------------------------------------
1 | Creating a new master
2 | =====================
3 |
--------------------------------------------------------------------------------
/canopen/sphinx/developers-guide/overview.rst:
--------------------------------------------------------------------------------
1 | Overview
2 | ========
3 | ros2_canopen provides nodes for interfacing with CANopen devices. The library builds upon the professional and open source
4 | lelycore canopen library as opposed to the previous ros_canopen stack.
5 | In ros2_canopen the bus configuration is simplified through the use of
6 | lelycore's configutaration toolchain.
7 |
8 | ros2_canopen contains a number of packages that serve different serve different purposes.
9 |
10 | * **canopen**:
11 |
12 | Meta-package for easy installation and contains overall documentation
13 | of the ros2_canopen stack.
14 |
15 | * **lely_core_libraries**:
16 |
17 | A colcon package wrapper for the lelycore canopen library, for convenient
18 | installation with rosdep.
19 |
20 | * **canopen_core**:
21 |
22 | Contains the core structures of the ros2_canopen stack such as the device manager
23 | and the master node and the driver node interface.
24 |
25 | * **canopen_base_driver**:
26 |
27 | This package contains the base implementation of a ROS2 CANopen device driver. It can base
28 | used by other drivers for easy extension.
29 |
30 | * **canopen_proxy_driver**:
31 |
32 | Contains an implementation of a proxy driver which simply forwards CANopen functionality
33 | for a specific device via ROS2 services and messages.
34 |
35 | * **canopen_402_driver**:
36 |
37 | Contains an implementation of the CIA402 profile for motion controllers and exposes
38 | the profiles functionalities via ROS2 services and messages. The implementation is
39 | copied from ros_canopen/canopen_402 and this package is licensed accordingly under
40 | GNU Lesser General Public License v3.0!
41 |
--------------------------------------------------------------------------------
/canopen/sphinx/images/configuration-flow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ros-industrial/ros2_canopen/f144f280f8e3c3f47491ae15e7f44ece1781db1a/canopen/sphinx/images/configuration-flow.png
--------------------------------------------------------------------------------
/canopen/sphinx/images/device-manager-usage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ros-industrial/ros2_canopen/f144f280f8e3c3f47491ae15e7f44ece1781db1a/canopen/sphinx/images/device-manager-usage.png
--------------------------------------------------------------------------------
/canopen/sphinx/images/device-manager.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ros-industrial/ros2_canopen/f144f280f8e3c3f47491ae15e7f44ece1781db1a/canopen/sphinx/images/device-manager.png
--------------------------------------------------------------------------------
/canopen/sphinx/images/prbt_rviz2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ros-industrial/ros2_canopen/f144f280f8e3c3f47491ae15e7f44ece1781db1a/canopen/sphinx/images/prbt_rviz2.png
--------------------------------------------------------------------------------
/canopen/sphinx/images/ros2-canopen-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ros-industrial/ros2_canopen/f144f280f8e3c3f47491ae15e7f44ece1781db1a/canopen/sphinx/images/ros2-canopen-logo.png
--------------------------------------------------------------------------------
/canopen/sphinx/images/system-interface.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ros-industrial/ros2_canopen/f144f280f8e3c3f47491ae15e7f44ece1781db1a/canopen/sphinx/images/system-interface.png
--------------------------------------------------------------------------------
/canopen/sphinx/index.rst:
--------------------------------------------------------------------------------
1 | ROS2 CANopen Stack
2 | ==================
3 |
4 | This is the documentation of the ROS2 CANopen stack.
5 |
6 | .. toctree::
7 | :maxdepth: 1
8 | :caption: Quickstart
9 | :glob:
10 |
11 | quickstart/installation
12 | quickstart/operation
13 | quickstart/examples
14 |
15 | .. toctree::
16 | :maxdepth: 1
17 | :caption: User Guide
18 | :glob:
19 |
20 | user-guide/operation
21 | user-guide/configuration
22 | user-guide/master
23 | user-guide/proxy-driver
24 | user-guide/cia402-driver
25 | user-guide/how-to-create-a-configuration
26 | user-guide/how-to-create-a-cia301-system
27 | user-guide/how-to-create-a-robot-system
28 |
29 |
30 | .. toctree::
31 | :maxdepth: 1
32 | :caption: Developer Guide
33 | :glob:
34 |
35 | developers-guide/design-objectives
36 | developers-guide/overview
37 | developers-guide/architecture
38 | developers-guide/new-driver
39 | developers-guide/new-master
40 | API Reference
41 |
42 | .. toctree::
43 | :maxdepth: 1
44 | :caption: Software Tests
45 | :glob:
46 |
47 | software-tests/**
48 |
49 | .. toctree::
50 | :maxdepth: 1
51 | :caption: Application Demos
52 | :glob:
53 |
54 | application/**
55 |
--------------------------------------------------------------------------------
/canopen/sphinx/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=sphinx-build
9 | )
10 | set SOURCEDIR=.
11 | set BUILDDIR=_build
12 |
13 | if "%1" == "" goto help
14 |
15 | %SPHINXBUILD% >NUL 2>NUL
16 | if errorlevel 9009 (
17 | echo.
18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
19 | echo.installed, then set the SPHINXBUILD environment variable to point
20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
21 | echo.may add the Sphinx directory to PATH.
22 | echo.
23 | echo.If you don't have Sphinx installed, grab it from
24 | echo.https://www.sphinx-doc.org/
25 | exit /b 1
26 | )
27 |
28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
29 | goto end
30 |
31 | :help
32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
33 |
34 | :end
35 | popd
36 |
--------------------------------------------------------------------------------
/canopen/sphinx/quickstart/examples.rst:
--------------------------------------------------------------------------------
1 | Running Examples
2 | ================
3 |
4 | In order to tryout the library a few examples are provided in the ``canopen_tests`` directory.
5 | You can run them if you have :ref:`started the vcan0 interface `.
6 |
7 | Service Interface
8 | ---------------------
9 |
10 | .. code-block:: bash
11 |
12 | ros2 launch canopen_tests cia402_setup.launch.py
13 |
14 |
15 | Managed Service Interface
16 | -------------------------
17 |
18 | .. code-block:: bash
19 |
20 | ros2 launch canopen_tests cia402_lifecycle_setup.launch.py
21 |
22 | ROS2 Control
23 | ------------
24 |
25 | Proxy Setup
26 | ,,,,,,,,,,,
27 |
28 | .. code-block:: bash
29 |
30 | ros2 launch canopen_tests canopen_system.launch.py
31 |
32 |
33 | CiA402 Setup
34 | ,,,,,,,,,,,,
35 |
36 | .. code-block:: bash
37 |
38 | ros2 launch canopen_tests cia402_system.launch.py
39 |
40 |
41 | Robot Setup
42 | ,,,,,,,,,,,,
43 |
44 | .. code-block:: bash
45 |
46 | ros2 launch canopen_tests robot_control_setup.launch.py
47 |
--------------------------------------------------------------------------------
/canopen/sphinx/quickstart/installation.rst:
--------------------------------------------------------------------------------
1 | Installation
2 | ===============================
3 | Clone ros2_canopen into your ROS2 workspace's source folder, install dependencies and
4 | build with colcon and your done.
5 |
6 | .. code-block:: console
7 |
8 | $ git clone https://github.com/ros-industrial/ros2_canopen.git
9 | $ cd ..
10 | $ rosdep install --from-paths src/ros2_canopen --ignore-src -r -y
11 | $ colcon build
12 |
--------------------------------------------------------------------------------
/canopen/sphinx/quickstart/operation.rst:
--------------------------------------------------------------------------------
1 | Setup CAN Controller
2 | ====================
3 | .. _quick-start-setup-can-controller:
4 |
5 | **Option 1**: Virtual CANController
6 |
7 | .. code-block:: console
8 |
9 | $ sudo modprobe vcan
10 | $ sudo ip link add dev vcan0 type vcan
11 | $ sudo ip link set vcan0 txqueuelen 1000
12 | $ sudo ip link set up vcan0
13 |
14 | **Option 2**: Peak CANController
15 |
16 | .. code-block:: console
17 |
18 | $ sudo modprobe peak_usb
19 | $ sudo ip link set can0 up type can bitrate 1000000
20 | $ sudo ip link set can0 txqueuelen 1000
21 | $ sudo ip link set up can0
22 |
23 | Bitrate depends on your bus and devices capabilities.
24 |
25 | **Option 3**: candleLight USB-CAN Adapter
26 |
27 | .. code-block:: console
28 |
29 | $ sudo modprobe gs_usb
30 | $ sudo ip link set can0 up type can bitrate 500000
31 | $ sudo ip link set can0 txqueuelen 1000
32 | $ sudo ip link set up can0
33 |
34 | Bitrate depends on your bus and devices capabilities.
35 |
36 | **Option 4**: Adapt these steps to other socketcan devices
37 |
--------------------------------------------------------------------------------
/canopen/sphinx/software-tests/proxy-driver-test.rst:
--------------------------------------------------------------------------------
1 | Lifecycle Proxy Driver Test
2 | ===========================
3 |
4 | .. csv-table:: Testdetails
5 | :header: "Detail", "Information"
6 | :delim: ;
7 |
8 | Package; canopen_tests
9 | Test file; launch_tests/test_lifecycle_proxy_driver.py
10 | Description; Tests nmt, sdo and lifecycle of lifecycle proxy driver
11 | Prerequisites; vcan0 must be available
12 |
13 | Proxy Driver Test
14 | ===========================
15 |
16 | .. csv-table:: Testdetails
17 | :header: "Detail", "Information"
18 | :delim: ;
19 |
20 | Package; canopen_tests
21 | Test file; launch_tests/test_proxy_driver.py
22 | Description; Tests nmt, sdo and lifecycle of proxy driver
23 | Prerequisites; vcan0 must be available
24 |
--------------------------------------------------------------------------------
/canopen/sphinx/user-guide/master.rst:
--------------------------------------------------------------------------------
1 | Master Driver
2 | =============
3 |
4 | The master driver handles the creation of the necessary can interface and sets up a canopen event loop which drivers can hook onto.
5 | In addition, the node offers services for communicating with nodes via nmt and sdo.
6 |
7 | .. csv-table:: Master Drivers
8 | :header: Type, Package, Name
9 | :widths: 30, 20, 50
10 |
11 | lifecycle, canopen_master_driver, ros2_canopen::LifecycleMasterDriver
12 | simple, canopen_master_driver, ros2_canopen::MasterDriver
13 |
14 |
15 | Services
16 | --------
17 |
18 | .. list-table::
19 | :widths: 30 20 50
20 | :header-rows: 1
21 |
22 | * - Services
23 | - Type
24 | - Description
25 | * - ~/read_sdo
26 | - COReadID
27 | - Reads an SDO object specified by Index, Subindex and Datatype of the device with the specified nodeid.
28 | * - ~/write_sdo
29 | - COWriteID
30 | - Writes Data to an SDO object specified by Index, Subindex and Datatype on the device with the specified nodeid.
31 | * - ~/set_nmt
32 | - CONmtID
33 | - Sends the NMT command to the device with the specified nodeid
34 |
--------------------------------------------------------------------------------
/canopen/sphinx/user-guide/operation.rst:
--------------------------------------------------------------------------------
1 | Operation
2 | =========
3 |
4 | The ros2_canopen stack can be used in three different ways:
5 |
6 | * standard nodes container
7 | * managed nodes container
8 | * ros2_control system interface with standard nodes
9 |
10 |
11 | Simple nodes container
12 | """"""""""""""""""""""""
13 | The standard node container mode bundles the master and all slave driver nodes in one specialised
14 | container called device container. All nodes are simple ROS 2 nodes and expose a publish and subscribe
15 | as well as a service interfaces. Once the device container is started, all nodes are brought up
16 | and ready to be used.
17 |
18 | **Purpose**:
19 | The simple nodes container is thought for applications where the user needs a simple and
20 | easy to launch interface and does not need any realtime control capabilities as provided by
21 | ros2_control.
22 |
23 | Managed nodes container
24 | """"""""""""""""""""""""""
25 | The managed nodes container has the same properties as the standard nodes container.
26 | The exception is, that all nodes are lifecycle nodes and there is a special node called
27 | lifecycle manager. The user can use the lifecycle manager to control the lifecycle of
28 | all nodes in the container.
29 |
30 | **Purpose**:
31 | The managed nodes container is thought for applications where the user wants to have
32 | more runtime recovery options than killing and restarting the container.
33 |
34 |
35 | ROS 2 control system interface
36 | """"""""""""""""""""""""""""""
37 | The ros2_control interface is currently build on top of the simple nodes container. In
38 | addition to the standard nodes container the ros2_control system interface provides a
39 | hardware interface that can be used to control the devices on the bus. Currently, three
40 | different system interfaces are provided:
41 |
42 | * canopen_ros2_control/CANopenSystem
43 | * canopen_ros2_control/CIA402System
44 | * canopen_ros2_control/RobotSystem
45 |
46 | **Purpose**:
47 | The ROS 2 control system interfaces are thought for control applications that require
48 | low latencies.
49 |
--------------------------------------------------------------------------------
/canopen/sphinx/user-guide/proxy-driver.rst:
--------------------------------------------------------------------------------
1 | Proxy Driver
2 | ===================
3 | A proxy driver which simply forwards CANopen functionality for a specific device via ROS2 services and messages.
4 |
5 | .. csv-table:: Proxy Drivers
6 | :header: Type, Package, Name
7 | :widths: 30, 20, 50
8 |
9 | lifecycle, canopen_proxy_driver, ros2_canopen::LifecycleProxyDriver
10 | simple, canopen_proxy_driver, ros2_canopen::ProxyDriver
11 |
12 | Services
13 | --------
14 |
15 | .. list-table::
16 | :widths: 30 20 50
17 | :header-rows: 1
18 | :align: left
19 |
20 | * - Services
21 | - Type
22 | - Description
23 | * - ~/nmt_reset_node
24 | - Trigger
25 | - Resets CANopen Device the Proxy Device Node manages.
26 | * - ~/sdo_read
27 | - CORead
28 | - Reads an SDO object from the specified index, subindex and datatype of the remote device.
29 | * - ~/sdo_write
30 | - COWrite
31 | - Writes data to an SDO object on the specified index, subindex and datatype of the remote device.
32 |
33 |
34 | Publishers
35 | ----------
36 |
37 | .. list-table::
38 | :widths: 30 20 50
39 | :header-rows: 1
40 | :align: left
41 |
42 | * - Topic
43 | - Type
44 | - Description
45 | * - ~/nmt_state
46 | - String
47 | - Publishes NMT state on change
48 | * - ~/rpdo
49 | - COData
50 | - Publishes received PDO objects on reception
51 |
52 | Subscribers
53 | -----------
54 |
55 | .. list-table::
56 | :widths: 30 20 50
57 | :header-rows: 1
58 |
59 | * - Topic
60 | - Type
61 | - Description
62 | * - ~/tpdo
63 | - COData
64 | - Writes received data to remote device if the specified object is RPDO mapped on remote device.
65 |
--------------------------------------------------------------------------------
/canopen_402_driver/CHANGELOG.rst:
--------------------------------------------------------------------------------
1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 | Changelog for package canopen_402_driver
3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4 |
5 | 0.2.9 (2024-04-16)
6 | ------------------
7 | * Update the lely_core_libraries hash to the latest.
8 | * fix ci build error
9 | * Contributors: Vishnuprasad Prachandabhanu
10 |
11 | 0.3.0 (2024-12-12)
12 | ------------------
13 | * Reformat using pre-commit
14 | * Implement position offsets
15 | * pre-commit fix
16 | * impl operation mode
17 | * Add cyclic torque mode to cia402 driver and robot system controller (`#293 `_)
18 | * Add base functions for switching to cyclic torque mode
19 | * Add cyclic torque mode as effort interface to robot_system controller
20 | * Add documentation about cyclic torque mode.
21 | ---------
22 | Co-authored-by: Christoph Hellmann Santos
23 |
24 | 0.2.12 (2024-04-22)
25 | -------------------
26 | * 0.2.9
27 | * forthcoming
28 | * Merge pull request `#267 `_ from clalancette/clalancette/update-lely-core-hash
29 | Update the lely_core_libraries hash to the latest.
30 | * fix ci build error
31 | * Contributors: Vishnuprasad Prachandabhanu, ipa-vsp
32 |
33 | 0.2.8 (2024-01-19)
34 | ------------------
35 |
36 | 0.2.7 (2023-06-30)
37 | ------------------
38 | * Add missing license headers and activate ament_copyright
39 | * Fix maintainer naming
40 | * Contributors: Christoph Hellmann Santos
41 |
42 | 0.2.6 (2023-06-24)
43 | ------------------
44 |
45 | 0.2.5 (2023-06-23)
46 | ------------------
47 |
48 | 0.2.4 (2023-06-22)
49 | ------------------
50 |
51 | 0.2.3 (2023-06-22)
52 | ------------------
53 |
54 | 0.2.2 (2023-06-21)
55 | ------------------
56 |
57 | 0.2.1 (2023-06-21)
58 | ------------------
59 | * Fix boost/std placeholders ambiguity in older boost versions
60 | * Contributors: Christoph Hellmann Santos
61 |
62 | 0.2.0 (2023-06-14)
63 | ------------------
64 | * Created package
65 | * Contributors: Borong Yuan, Błażej Sowa, Christoph Hellmann Santos, Denis Štogl, G.A. vd. Hoorn, Lovro, Vishnuprasad Prachandabhanu, livanov93
66 |
--------------------------------------------------------------------------------
/canopen_402_driver/include/canopen_402_driver/default_homing_mode.hpp:
--------------------------------------------------------------------------------
1 | // Copyright 2023 Christoph Hellmann Santos
2 | // Copyright 2014-2022 Authors of ros_canopen
3 | //
4 | // This program is free software: you can redistribute it and/or modify
5 | // it under the terms of the GNU General Public License as published by
6 | // the Free Software Foundation, either version 3 of the License, or
7 | // (at your option) any later version.
8 | //
9 | // This program is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | // GNU General Public License for more details.
13 | //
14 | // You should have received a copy of the GNU General Public License
15 | // along with this program. If not, see .
16 | //
17 |
18 | #ifndef DEFAULT_HOMING_MODE_HPP
19 | #define DEFAULT_HOMING_MODE_HPP
20 | #include
21 | #include "canopen_base_driver/lely_driver_bridge.hpp"
22 | #include "homing_mode.hpp"
23 |
24 | namespace ros2_canopen
25 | {
26 |
27 | class DefaultHomingMode : public HomingMode
28 | {
29 | const uint16_t index = 0x6098;
30 | std::shared_ptr driver;
31 |
32 | std::atomic execute_;
33 |
34 | std::mutex mutex_;
35 | std::condition_variable cond_;
36 | uint16_t status_;
37 |
38 | const int homing_timeout_seconds_;
39 |
40 | enum SW_masks
41 | {
42 | MASK_Reached = (1 << State402::SW_Target_reached),
43 | MASK_Attained = (1 << SW_Attained),
44 | MASK_Error = (1 << SW_Error),
45 | };
46 | bool error(const std::string & msg)
47 | {
48 | execute_ = false;
49 | std::cout << msg << std::endl;
50 | return false;
51 | }
52 |
53 | public:
54 | DefaultHomingMode(std::shared_ptr driver, int homing_timeout_seconds)
55 | : homing_timeout_seconds_(homing_timeout_seconds)
56 | {
57 | this->driver = driver;
58 | }
59 | virtual bool start();
60 | virtual bool read(const uint16_t & sw);
61 | virtual bool write(OpModeAccesser & cw);
62 |
63 | virtual bool executeHoming();
64 | };
65 | } // namespace ros2_canopen
66 | #endif // DEFAULT_HOMING_MODE_HPP
67 |
--------------------------------------------------------------------------------
/canopen_402_driver/include/canopen_402_driver/homing_mode.hpp:
--------------------------------------------------------------------------------
1 | // Copyright 2023 Christoph Hellmann Santos
2 | // Copyright 2014-2022 Authors of ros_canopen
3 | //
4 | // This program is free software: you can redistribute it and/or modify
5 | // it under the terms of the GNU General Public License as published by
6 | // the Free Software Foundation, either version 3 of the License, or
7 | // (at your option) any later version.
8 | //
9 | // This program is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | // GNU General Public License for more details.
13 | //
14 | // You should have received a copy of the GNU General Public License
15 | // along with this program. If not, see .
16 | //
17 |
18 | #ifndef HOMING_MODE_HPP
19 | #define HOMING_MODE_HPP
20 | #include "base.hpp"
21 | #include "mode.hpp"
22 |
23 | namespace ros2_canopen
24 | {
25 | class HomingMode : public Mode
26 | {
27 | protected:
28 | enum SW_bits
29 | {
30 | SW_Attained = State402::SW_Operation_mode_specific0,
31 | SW_Error = State402::SW_Operation_mode_specific1,
32 | };
33 | enum CW_bits
34 | {
35 | CW_StartHoming = Command402::CW_Operation_mode_specific0,
36 | };
37 |
38 | public:
39 | HomingMode() : Mode(MotorBase::Homing) {}
40 | virtual bool executeHoming() = 0;
41 | };
42 | } // namespace ros2_canopen
43 |
44 | #endif // HOMING_MODE_HPP
45 |
--------------------------------------------------------------------------------
/canopen_402_driver/include/canopen_402_driver/mode.hpp:
--------------------------------------------------------------------------------
1 | // Copyright 2023 Christoph Hellmann Santos
2 | // Copyright 2014-2022 Authors of ros_canopen
3 | //
4 | // This program is free software: you can redistribute it and/or modify
5 | // it under the terms of the GNU General Public License as published by
6 | // the Free Software Foundation, either version 3 of the License, or
7 | // (at your option) any later version.
8 | //
9 | // This program is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | // GNU General Public License for more details.
13 | //
14 | // You should have received a copy of the GNU General Public License
15 | // along with this program. If not, see .
16 | //
17 |
18 | #ifndef CANOPEN_402_DRIVER_MODE_HPP
19 | #define CANOPEN_402_DRIVER_MODE_HPP
20 |
21 | #include
22 | #include
23 | #include "command.hpp"
24 | #include "state.hpp"
25 | #include "word_accessor.hpp"
26 |
27 | namespace ros2_canopen
28 | {
29 | class Mode
30 | {
31 | public:
32 | const uint16_t mode_id_;
33 | Mode(uint16_t id) : mode_id_(id) {}
34 | typedef WordAccessor<
35 | (1 << Command402::CW_Operation_mode_specific0) |
36 | (1 << Command402::CW_Operation_mode_specific1) |
37 | (1 << Command402::CW_Operation_mode_specific2) | (1 << Command402::CW_Operation_mode_specific3)>
38 | OpModeAccesser;
39 | virtual bool start() = 0;
40 | virtual bool read(const uint16_t & sw) = 0;
41 | virtual bool write(OpModeAccesser & cw) = 0;
42 | virtual bool setTarget(const double & val) { return false; }
43 | virtual ~Mode() {}
44 | };
45 | typedef std::shared_ptr ModeSharedPtr;
46 | } // namespace ros2_canopen
47 |
48 | #endif // CANOPEN_402_DRIVER_MODE_HPP
49 |
--------------------------------------------------------------------------------
/canopen_402_driver/include/canopen_402_driver/mode_forward_helper.hpp:
--------------------------------------------------------------------------------
1 | // Copyright 2023 Christoph Hellmann Santos
2 | // Copyright 2014-2022 Authors of ros_canopen
3 | //
4 | // This program is free software: you can redistribute it and/or modify
5 | // it under the terms of the GNU General Public License as published by
6 | // the Free Software Foundation, either version 3 of the License, or
7 | // (at your option) any later version.
8 | //
9 | // This program is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | // GNU General Public License for more details.
13 | //
14 | // You should have received a copy of the GNU General Public License
15 | // along with this program. If not, see .
16 | //
17 |
18 | #ifndef MODE_FORWARD_HELPER_HPP
19 | #define MODE_FORWARD_HELPER_HPP
20 |
21 | #include
22 | #include
23 | #include "canopen_base_driver/lely_driver_bridge.hpp"
24 | #include "mode_target_helper.hpp"
25 |
26 | namespace ros2_canopen
27 | {
28 |
29 | template
30 | class ModeForwardHelper : public ModeTargetHelper
31 | {
32 | std::shared_ptr driver;
33 |
34 | public:
35 | ModeForwardHelper(std::shared_ptr driver) : ModeTargetHelper(ID)
36 | {
37 | this->driver = driver;
38 | }
39 | virtual bool read(const uint16_t & sw) { return true; }
40 | virtual bool write(Mode::OpModeAccesser & cw)
41 | {
42 | if (this->hasTarget())
43 | {
44 | cw = cw.get() | CW_MASK;
45 |
46 | driver->universal_set_value(OBJ, SUB, this->getTarget());
47 | return true;
48 | }
49 | else
50 | {
51 | cw = cw.get() & ~CW_MASK;
52 | return false;
53 | }
54 | }
55 | };
56 | } // namespace ros2_canopen
57 |
58 | #endif // MODE_FORWARD_HELPER_HPP
59 |
--------------------------------------------------------------------------------
/canopen_402_driver/include/canopen_402_driver/state.hpp:
--------------------------------------------------------------------------------
1 | // Copyright 2023 Christoph Hellmann Santos
2 | // Copyright 2014-2022 Authors of ros_canopen
3 | //
4 | // This program is free software: you can redistribute it and/or modify
5 | // it under the terms of the GNU General Public License as published by
6 | // the Free Software Foundation, either version 3 of the License, or
7 | // (at your option) any later version.
8 | //
9 | // This program is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | // GNU General Public License for more details.
13 | //
14 | // You should have received a copy of the GNU General Public License
15 | // along with this program. If not, see .
16 | //
17 |
18 | #ifndef CANOPEN_402_DRIVER_STATE_HPP
19 | #define CANOPEN_402_DRIVER_STATE_HPP
20 |
21 | #include
22 | #include
23 | #include
24 |
25 | namespace ros2_canopen
26 | {
27 | class State402
28 | {
29 | public:
30 | enum StatusWord
31 | {
32 | SW_Ready_To_Switch_On = 0,
33 | SW_Switched_On = 1,
34 | SW_Operation_enabled = 2,
35 | SW_Fault = 3,
36 | SW_Voltage_enabled = 4,
37 | SW_Quick_stop = 5,
38 | SW_Switch_on_disabled = 6,
39 | SW_Warning = 7,
40 | SW_Manufacturer_specific0 = 8,
41 | SW_Remote = 9,
42 | SW_Target_reached = 10,
43 | SW_Internal_limit = 11,
44 | SW_Operation_mode_specific0 = 12,
45 | SW_Operation_mode_specific1 = 13,
46 | SW_Manufacturer_specific1 = 14,
47 | SW_Manufacturer_specific2 = 15
48 | };
49 | enum InternalState
50 | {
51 | Unknown = 0,
52 | Start = 0,
53 | Not_Ready_To_Switch_On = 1,
54 | Switch_On_Disabled = 2,
55 | Ready_To_Switch_On = 3,
56 | Switched_On = 4,
57 | Operation_Enable = 5,
58 | Quick_Stop_Active = 6,
59 | Fault_Reaction_Active = 7,
60 | Fault = 8,
61 | };
62 | InternalState getState();
63 | InternalState read(uint16_t sw);
64 | bool waitForNewState(
65 | const std::chrono::steady_clock::time_point & abstime, InternalState & state);
66 | State402() : state_(Unknown) {}
67 |
68 | private:
69 | std::condition_variable cond_;
70 | std::mutex mutex_;
71 | InternalState state_;
72 | };
73 | } // namespace ros2_canopen
74 |
75 | #endif // CANOPEN_402_DRIVER_STATE_HPP
76 |
--------------------------------------------------------------------------------
/canopen_402_driver/include/canopen_402_driver/visibility_control.h:
--------------------------------------------------------------------------------
1 | // Copyright 2023 Christoph Hellmann Santos
2 | //
3 | // This program is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // This program is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with this program. If not, see .
15 | //
16 | #ifndef CANOPEN_402_DRIVER__VISIBILITY_CONTROL_H_
17 | #define CANOPEN_402_DRIVER__VISIBILITY_CONTROL_H_
18 |
19 | // This logic was borrowed (then namespaced) from the examples on the gcc wiki:
20 | // https://gcc.gnu.org/wiki/Visibility
21 |
22 | #if defined _WIN32 || defined __CYGWIN__
23 | #ifdef __GNUC__
24 | #define CANOPEN_402_DRIVER_EXPORT __attribute__((dllexport))
25 | #define CANOPEN_402_DRIVER_IMPORT __attribute__((dllimport))
26 | #else
27 | #define CANOPEN_402_DRIVER_EXPORT __declspec(dllexport)
28 | #define CANOPEN_402_DRIVER_IMPORT __declspec(dllimport)
29 | #endif
30 | #ifdef CANOPEN_402_DRIVER_BUILDING_LIBRARY
31 | #define CANOPEN_402_DRIVER_PUBLIC CANOPEN_402_DRIVER_EXPORT
32 | #else
33 | #define CANOPEN_402_DRIVER_PUBLIC CANOPEN_402_DRIVER_IMPORT
34 | #endif
35 | #define CANOPEN_402_DRIVER_PUBLIC_TYPE CANOPEN_402_DRIVER_PUBLIC
36 | #define CANOPEN_402_DRIVER_LOCAL
37 | #else
38 | #define CANOPEN_402_DRIVER_EXPORT __attribute__((visibility("default")))
39 | #define CANOPEN_402_DRIVER_IMPORT
40 | #if __GNUC__ >= 4
41 | #define CANOPEN_402_DRIVER_PUBLIC __attribute__((visibility("default")))
42 | #define CANOPEN_402_DRIVER_LOCAL __attribute__((visibility("hidden")))
43 | #else
44 | #define CANOPEN_402_DRIVER_PUBLIC
45 | #define CANOPEN_402_DRIVER_LOCAL
46 | #endif
47 | #define CANOPEN_402_DRIVER_PUBLIC_TYPE
48 | #endif
49 |
50 | #endif // CANOPEN_402_DRIVER__VISIBILITY_CONTROL_H_
51 |
--------------------------------------------------------------------------------
/canopen_402_driver/include/canopen_402_driver/word_accessor.hpp:
--------------------------------------------------------------------------------
1 | // Copyright 2023 Christoph Hellmann Santos
2 | // Copyright 2014-2022 Authors of ros_canopen
3 | //
4 | // This program is free software: you can redistribute it and/or modify
5 | // it under the terms of the GNU General Public License as published by
6 | // the Free Software Foundation, either version 3 of the License, or
7 | // (at your option) any later version.
8 | //
9 | // This program is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | // GNU General Public License for more details.
13 | //
14 | // You should have received a copy of the GNU General Public License
15 | // along with this program. If not, see .
16 | //
17 |
18 | #ifndef WORD_ACCESSOR_HPP
19 | #define WORD_ACCESSOR_HPP
20 |
21 | #include
22 |
23 | namespace ros2_canopen
24 | {
25 | template
26 | class WordAccessor
27 | {
28 | uint16_t & word_;
29 |
30 | public:
31 | WordAccessor(uint16_t & word) : word_(word) {}
32 | bool set(uint8_t bit)
33 | {
34 | uint16_t val = MASK & (1 << bit);
35 | word_ |= val;
36 | return val;
37 | }
38 | bool reset(uint8_t bit)
39 | {
40 | uint16_t val = MASK & (1 << bit);
41 | word_ &= ~val;
42 | return val;
43 | }
44 | bool get(uint8_t bit) const { return word_ & (1 << bit); }
45 | uint16_t get() const { return word_ & MASK; }
46 | WordAccessor & operator=(const uint16_t & val)
47 | {
48 | word_ = (word_ & ~MASK) | (val & MASK);
49 | return *this;
50 | }
51 | };
52 | } // namespace ros2_canopen
53 |
54 | #endif // WORD_ACCESSOR_HPP
55 |
--------------------------------------------------------------------------------
/canopen_402_driver/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | canopen_402_driver
5 | 0.3.0
6 | Driiver for devices implementing CIA402 profile
7 | Christoph Hellmann Santos
8 | LGPL-v3
9 |
10 | ament_cmake_ros
11 |
12 | boost
13 | canopen_base_driver
14 | canopen_core
15 | canopen_interfaces
16 | canopen_proxy_driver
17 | rclcpp
18 | rclcpp_components
19 | rclcpp_lifecycle
20 | sensor_msgs
21 | std_srvs
22 |
23 | ament_lint_auto
24 |
25 |
26 | ament_cmake
27 |
28 |
29 |
--------------------------------------------------------------------------------
/canopen_402_driver/src/cia402_driver.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2023 Christoph Hellmann Santos
2 | //
3 | // This program is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // This program is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with this program. If not, see .
15 | //
16 |
17 | #include "canopen_402_driver/cia402_driver.hpp"
18 |
19 | using namespace ros2_canopen;
20 |
21 | Cia402Driver::Cia402Driver(rclcpp::NodeOptions node_options) : CanopenDriver(node_options)
22 | {
23 | node_canopen_402_driver_ =
24 | std::make_shared>(this);
25 | node_canopen_driver_ =
26 | std::static_pointer_cast(node_canopen_402_driver_);
27 | }
28 |
29 | #include "rclcpp_components/register_node_macro.hpp"
30 | RCLCPP_COMPONENTS_REGISTER_NODE(ros2_canopen::Cia402Driver)
31 |
--------------------------------------------------------------------------------
/canopen_402_driver/src/lifecycle_cia402_driver.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2023 Christoph Hellmann Santos
2 | //
3 | // This program is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // This program is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with this program. If not, see .
15 | //
16 |
17 | #include "canopen_402_driver/lifecycle_cia402_driver.hpp"
18 |
19 | using namespace ros2_canopen;
20 |
21 | LifecycleCia402Driver::LifecycleCia402Driver(rclcpp::NodeOptions node_options)
22 | : LifecycleCanopenDriver(node_options)
23 | {
24 | node_canopen_402_driver_ =
25 | std::make_shared>(this);
26 | node_canopen_driver_ =
27 | std::static_pointer_cast(node_canopen_402_driver_);
28 | }
29 |
30 | #include "rclcpp_components/register_node_macro.hpp"
31 | RCLCPP_COMPONENTS_REGISTER_NODE(ros2_canopen::LifecycleCia402Driver)
32 |
--------------------------------------------------------------------------------
/canopen_402_driver/src/node_interfaces/node_canopen_402_driver.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2023 Christoph Hellmann Santos
2 | //
3 | // This program is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // This program is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with this program. If not, see .
15 | //
16 |
17 | #include "canopen_402_driver/node_interfaces/node_canopen_402_driver.hpp"
18 | #include "canopen_402_driver/node_interfaces/node_canopen_402_driver_impl.hpp"
19 | #include "canopen_core/driver_error.hpp"
20 |
21 | using namespace ros2_canopen::node_interfaces;
22 |
23 | template class ros2_canopen::node_interfaces::NodeCanopen402Driver;
24 | template class ros2_canopen::node_interfaces::NodeCanopen402Driver;
25 |
--------------------------------------------------------------------------------
/canopen_402_driver/test/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | ament_add_gtest(test_driver_component
2 | test_driver_component.cpp
3 | )
4 | ament_target_dependencies(test_driver_component
5 | ${dependencies}
6 | )
7 | target_include_directories(test_driver_component PUBLIC
8 | ${CMAKE_CURRENT_SOURCE_DIR}/../include/
9 | )
10 |
--------------------------------------------------------------------------------
/canopen_402_driver/test/test_driver_component.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2023 Christoph Hellmann Santos
2 | //
3 | // This program is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // This program is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with this program. If not, see .
15 | //
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include "canopen_base_driver/node_interfaces/node_canopen_base_driver.hpp"
22 | #include "gtest/gtest.h"
23 | using namespace rclcpp_components;
24 |
25 | TEST(ComponentLoad, test_load_component_1)
26 | {
27 | rclcpp::init(0, nullptr);
28 | auto exec = std::make_shared();
29 | auto manager = std::make_shared(exec);
30 |
31 | std::vector resources =
32 | manager->get_component_resources("canopen_402_driver");
33 |
34 | EXPECT_EQ(2u, resources.size());
35 |
36 | auto factory = manager->create_component_factory(resources[0]);
37 | auto instance_wrapper =
38 | factory->create_node_instance(rclcpp::NodeOptions().use_global_arguments(false));
39 |
40 | rclcpp::shutdown();
41 | }
42 |
43 | TEST(ComponentLoad, test_load_component_2)
44 | {
45 | rclcpp::init(0, nullptr);
46 | auto exec = std::make_shared();
47 | auto manager = std::make_shared(exec);
48 |
49 | std::vector resources =
50 | manager->get_component_resources("canopen_402_driver");
51 |
52 | EXPECT_EQ(2u, resources.size());
53 |
54 | auto factory = manager->create_component_factory(resources[1]);
55 | auto instance_wrapper =
56 | factory->create_node_instance(rclcpp::NodeOptions().use_global_arguments(false));
57 |
58 | rclcpp::shutdown();
59 | }
60 |
--------------------------------------------------------------------------------
/canopen_base_driver/CHANGELOG.rst:
--------------------------------------------------------------------------------
1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 | Changelog for package canopen_base_driver
3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4 |
5 | 0.2.9 (2024-04-16)
6 | ------------------
7 | * Add timeouts
8 | * Contributors: Vishnuprasad Prachandabhanu
9 |
10 | 0.3.0 (2024-12-12)
11 | ------------------
12 |
13 | 0.2.12 (2024-04-22)
14 | -------------------
15 | * Merge pull request `#280 `_ from ipa-vsp/fix/yaml-build-error
16 | Fix undefined reference to yaml library
17 | * pre-commit update
18 | * Merge pull request `#261 `_ from gsalinas/configurable-sdo-timeout
19 | Configurable SDO timeout
20 | * 0.2.9
21 | * forthcoming
22 | * Merge pull request `#220 `_ from ipa-vsp/feature/timeout-config
23 | Add timeouts
24 | * Set SDO timeout from node config.
25 | * Replace two more hardcoded timeouts.
26 | * Include timeout in documentation comment for LelyDriverBridge.
27 | * Make 20ms a default argument of the master & driver bridges.
28 | * change error to warn for testing
29 | * remove build warings
30 | * non transmit time from bus.yml
31 | * Contributors: Gerry Salinas, Vishnuprasad Prachandabhanu, ipa-vsp
32 |
33 | 0.2.8 (2024-01-19)
34 | ------------------
35 |
36 | 0.2.7 (2023-06-30)
37 | ------------------
38 | * Add missing license headers and activate ament_copyright
39 | * Fix maintainer naming
40 | * Update printed output in lely_driver_bridge.cpp
41 | * Contributors: Christoph Hellmann Santos, yos627
42 |
43 | 0.2.6 (2023-06-24)
44 | ------------------
45 |
46 | 0.2.5 (2023-06-23)
47 | ------------------
48 |
49 | 0.2.4 (2023-06-22)
50 | ------------------
51 |
52 | 0.2.3 (2023-06-22)
53 | ------------------
54 |
55 | 0.2.2 (2023-06-21)
56 | ------------------
57 |
58 | 0.2.1 (2023-06-21)
59 | ------------------
60 | * Fix base driver lifecyle
61 | * Fix node polling mode in base driver
62 | * Contributors: Błażej Sowa, Christoph Hellmann Santos
63 |
64 | 0.2.0 (2023-06-14)
65 | ------------------
66 | * Created package
67 | * Contributors: Błażej Sowa, Christoph Hellmann Santos, Denis Štogl, Lovro, Vishnuprasad Prachandabhanu
68 |
--------------------------------------------------------------------------------
/canopen_base_driver/include/canopen_base_driver/base_driver.hpp:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Christoph Hellmann Santos
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 | #ifndef CANOPEN_BASE_DRIVER__CANOPEN_BASE_DRIVER_HPP_
15 | #define CANOPEN_BASE_DRIVER__CANOPEN_BASE_DRIVER_HPP_
16 |
17 | #include "canopen_base_driver/node_interfaces/node_canopen_base_driver.hpp"
18 | #include "canopen_core/driver_node.hpp"
19 |
20 | namespace ros2_canopen
21 | {
22 | /**
23 | * @brief Abstract Class for a CANopen Device Node
24 | *
25 | * This class provides the base functionality for creating a
26 | * CANopen device node. It provides callbacks for nmt and rpdo.
27 | */
28 | class BaseDriver : public ros2_canopen::CanopenDriver
29 | {
30 | std::shared_ptr> node_canopen_base_driver_;
31 |
32 | public:
33 | BaseDriver(rclcpp::NodeOptions node_options = rclcpp::NodeOptions());
34 |
35 | void register_nmt_state_cb(std::function nmt_state_cb)
36 | {
37 | node_canopen_base_driver_->register_nmt_state_cb(nmt_state_cb);
38 | }
39 |
40 | void register_rpdo_cb(std::function rpdo_cb)
41 | {
42 | node_canopen_base_driver_->register_rpdo_cb(rpdo_cb);
43 | }
44 | };
45 | } // namespace ros2_canopen
46 |
47 | #endif // CANOPEN_BASE_DRIVER__CANOPEN_BASE_DRIVER_HPP_
48 |
--------------------------------------------------------------------------------
/canopen_base_driver/include/canopen_base_driver/lifecycle_base_driver.hpp:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Christoph Hellmann Santos
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 | #ifndef CANOPEN_BASE_DRIVER__CANOPEN_BASE_DRIVER_HPP_
15 | #define CANOPEN_BASE_DRIVER__CANOPEN_BASE_DRIVER_HPP_
16 |
17 | #include "canopen_base_driver/node_interfaces/node_canopen_base_driver.hpp"
18 | #include "canopen_core/driver_node.hpp"
19 |
20 | namespace ros2_canopen
21 | {
22 | /**
23 | * @brief Lifecycle Base Driver
24 | *
25 | * A very basic driver without any functionality.
26 | *
27 | */
28 | class LifecycleBaseDriver : public ros2_canopen::LifecycleCanopenDriver
29 | {
30 | std::shared_ptr>
31 | node_canopen_base_driver_;
32 |
33 | public:
34 | LifecycleBaseDriver(rclcpp::NodeOptions node_options = rclcpp::NodeOptions());
35 |
36 | void register_nmt_state_cb(std::function nmt_state_cb)
37 | {
38 | node_canopen_base_driver_->register_nmt_state_cb(nmt_state_cb);
39 | }
40 |
41 | void register_rpdo_cb(std::function rpdo_cb)
42 | {
43 | node_canopen_base_driver_->register_rpdo_cb(rpdo_cb);
44 | }
45 | };
46 | } // namespace ros2_canopen
47 |
48 | #endif // CANOPEN_BASE_DRIVER__CANOPEN_BASE_DRIVER_HPP_
49 |
--------------------------------------------------------------------------------
/canopen_base_driver/include/canopen_base_driver/visibility_control.h:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Christoph Hellmann Santos
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 | #ifndef CANOPEN_BASE_DRIVER__VISIBILITY_CONTROL_H_
16 | #define CANOPEN_BASE_DRIVER__VISIBILITY_CONTROL_H_
17 |
18 | // This logic was borrowed (then namespaced) from the examples on the gcc wiki:
19 | // https://gcc.gnu.org/wiki/Visibility
20 |
21 | #if defined _WIN32 || defined __CYGWIN__
22 | #ifdef __GNUC__
23 | #define CANOPEN_BASE_DRIVER_EXPORT __attribute__((dllexport))
24 | #define CANOPEN_BASE_DRIVER_IMPORT __attribute__((dllimport))
25 | #else
26 | #define CANOPEN_BASE_DRIVER_EXPORT __declspec(dllexport)
27 | #define CANOPEN_BASE_DRIVER_IMPORT __declspec(dllimport)
28 | #endif
29 | #ifdef CANOPEN_BASE_DRIVER_BUILDING_LIBRARY
30 | #define CANOPEN_BASE_DRIVER_PUBLIC CANOPEN_BASE_DRIVER_EXPORT
31 | #else
32 | #define CANOPEN_BASE_DRIVER_PUBLIC CANOPEN_BASE_DRIVER_IMPORT
33 | #endif
34 | #define CANOPEN_BASE_DRIVER_PUBLIC_TYPE CANOPEN_BASE_DRIVER_PUBLIC
35 | #define CANOPEN_BASE_DRIVER_LOCAL
36 | #else
37 | #define CANOPEN_BASE_DRIVER_EXPORT __attribute__((visibility("default")))
38 | #define CANOPEN_BASE_DRIVER_IMPORT
39 | #if __GNUC__ >= 4
40 | #define CANOPEN_BASE_DRIVER_PUBLIC __attribute__((visibility("default")))
41 | #define CANOPEN_BASE_DRIVER_LOCAL __attribute__((visibility("hidden")))
42 | #else
43 | #define CANOPEN_BASE_DRIVER_PUBLIC
44 | #define CANOPEN_BASE_DRIVER_LOCAL
45 | #endif
46 | #define CANOPEN_BASE_DRIVER_PUBLIC_TYPE
47 | #endif
48 |
49 | #endif // CANOPEN_BASE_DRIVER__VISIBILITY_CONTROL_H_
50 |
--------------------------------------------------------------------------------
/canopen_base_driver/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | canopen_base_driver
5 | 0.3.0
6 | Library containing abstract CANopen driver class for ros2_canopen
7 | Christoph Hellmann Santos
8 | Apache-2.0
9 |
10 | ament_cmake_ros
11 |
12 | canopen_core
13 | canopen_interfaces
14 | lely_core_libraries
15 | rclcpp
16 | rclcpp_components
17 | rclcpp_lifecycle
18 | std_msgs
19 | std_srvs
20 | boost
21 | diagnostic_updater
22 |
23 | ament_lint_auto
24 |
25 |
26 | ament_cmake
27 |
28 |
29 |
--------------------------------------------------------------------------------
/canopen_base_driver/src/base_driver.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Christoph Hellmann Santos
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 "canopen_base_driver/base_driver.hpp"
16 |
17 | using namespace ros2_canopen;
18 |
19 | BaseDriver::BaseDriver(rclcpp::NodeOptions node_options) : CanopenDriver(node_options)
20 | {
21 | node_canopen_base_driver_ =
22 | std::make_shared>(this);
23 | node_canopen_driver_ = std::static_pointer_cast(
24 | node_canopen_base_driver_);
25 | }
26 |
27 | #include "rclcpp_components/register_node_macro.hpp"
28 | RCLCPP_COMPONENTS_REGISTER_NODE(ros2_canopen::BaseDriver)
29 |
--------------------------------------------------------------------------------
/canopen_base_driver/src/lifecycle_base_driver.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Christoph Hellmann Santos
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 "canopen_base_driver/lifecycle_base_driver.hpp"
15 |
16 | using namespace ros2_canopen;
17 |
18 | LifecycleBaseDriver::LifecycleBaseDriver(rclcpp::NodeOptions node_options)
19 | : LifecycleCanopenDriver(node_options)
20 | {
21 | node_canopen_base_driver_ =
22 | std::make_shared>(this);
23 | node_canopen_driver_ = std::static_pointer_cast(
24 | node_canopen_base_driver_);
25 | }
26 |
27 | #include "rclcpp_components/register_node_macro.hpp"
28 | RCLCPP_COMPONENTS_REGISTER_NODE(ros2_canopen::LifecycleBaseDriver)
29 |
--------------------------------------------------------------------------------
/canopen_base_driver/src/node_interfaces/node_canopen_base_driver.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Christoph Hellmann Santos
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 "canopen_base_driver/node_interfaces/node_canopen_base_driver.hpp"
16 | #include "canopen_base_driver/node_interfaces/node_canopen_base_driver_impl.hpp"
17 | #include "canopen_core/driver_error.hpp"
18 |
19 | using namespace ros2_canopen::node_interfaces;
20 |
21 | template class ros2_canopen::node_interfaces::NodeCanopenBaseDriver;
22 | template class ros2_canopen::node_interfaces::NodeCanopenBaseDriver<
23 | rclcpp_lifecycle::LifecycleNode>;
24 |
--------------------------------------------------------------------------------
/canopen_base_driver/test/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | ament_add_gtest(test_node_canopen_base_driver_ros
2 | test_node_canopen_base_driver_ros.cpp
3 | )
4 | ament_target_dependencies(test_node_canopen_base_driver_ros
5 | ${dependencies}
6 | )
7 | target_include_directories(test_node_canopen_base_driver_ros PUBLIC
8 | ${CMAKE_CURRENT_SOURCE_DIR}/../include/
9 | )
10 | target_link_libraries(test_node_canopen_base_driver_ros
11 | node_canopen_base_driver
12 | )
13 |
14 |
15 |
16 |
17 | ament_add_gtest(test_base_driver_component
18 | test_base_driver_component.cpp
19 | )
20 | ament_target_dependencies(test_base_driver_component
21 | ${dependencies}
22 | )
23 | target_include_directories(test_base_driver_component PUBLIC
24 | ${CMAKE_CURRENT_SOURCE_DIR}/../include/
25 | )
26 |
27 |
28 | file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/master.dcf DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
29 |
--------------------------------------------------------------------------------
/canopen_base_driver/test/test_base_driver_component.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Christoph Hellmann Santos
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 "canopen_base_driver/node_interfaces/node_canopen_base_driver.hpp"
21 | #include "gtest/gtest.h"
22 | using namespace rclcpp_components;
23 |
24 | TEST(ComponentLoad, test_load_component_1)
25 | {
26 | rclcpp::init(0, nullptr);
27 | auto exec = std::make_shared();
28 | auto manager = std::make_shared(exec);
29 |
30 | std::vector resources =
31 | manager->get_component_resources("canopen_base_driver");
32 |
33 | EXPECT_EQ(2u, resources.size());
34 |
35 | auto factory = manager->create_component_factory(resources[0]);
36 | auto instance_wrapper =
37 | factory->create_node_instance(rclcpp::NodeOptions().use_global_arguments(false));
38 |
39 | rclcpp::shutdown();
40 | }
41 |
42 | TEST(ComponentLoad, test_load_component_2)
43 | {
44 | rclcpp::init(0, nullptr);
45 | auto exec = std::make_shared();
46 | auto manager = std::make_shared(exec);
47 |
48 | std::vector resources =
49 | manager->get_component_resources("canopen_base_driver");
50 |
51 | EXPECT_EQ(2u, resources.size());
52 |
53 | auto factory = manager->create_component_factory(resources[1]);
54 | auto instance_wrapper =
55 | factory->create_node_instance(rclcpp::NodeOptions().use_global_arguments(false));
56 |
57 | rclcpp::shutdown();
58 | }
59 |
--------------------------------------------------------------------------------
/canopen_core/CHANGELOG.rst:
--------------------------------------------------------------------------------
1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 | Changelog for package canopen_core
3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4 |
5 | 0.2.9 (2024-04-16)
6 | ------------------
7 | * Add timeouts
8 | * Contributors: Vishnuprasad Prachandabhanu, ipa-vsp
9 |
10 | 0.3.0 (2024-12-12)
11 | ------------------
12 |
13 | 0.2.12 (2024-04-22)
14 | -------------------
15 | * Merge pull request `#270 `_ from gsalinas/can-namespace-pr
16 | Put components loaded by the device container into its namespace, if any.
17 | * pre-commit update
18 | * Put components loaded by the device container into its namespace, if any.
19 | * Merge pull request `#280 `_ from ipa-vsp/fix/yaml-build-error
20 | Fix undefined reference to yaml library
21 | * fix undefined reference to yaml
22 | * Fix logging in device_container.cpp (`#277 `_)
23 | * 0.2.9
24 | * forthcoming
25 | * Merge pull request `#220 `_ from ipa-vsp/feature/timeout-config
26 | Add timeouts
27 | * change from 100ms to 2000ms
28 | * non transmit time from bus.yml
29 | * timeout for booting slave
30 | * Contributors: Christoph Hellmann Santos, Gerry Salinas, Vishnuprasad Prachandabhanu, ipa-vsp
31 |
32 | 0.2.8 (2024-01-19)
33 | ------------------
34 |
35 | 0.2.7 (2023-06-30)
36 | ------------------
37 | * Add missing license headers and activate ament_copyright
38 | * Fix maintainer naming
39 | * Contributors: Christoph Hellmann Santos
40 |
41 | 0.2.6 (2023-06-24)
42 | ------------------
43 |
44 | 0.2.5 (2023-06-23)
45 | ------------------
46 |
47 | 0.2.4 (2023-06-22)
48 | ------------------
49 |
50 | 0.2.3 (2023-06-22)
51 | ------------------
52 |
53 | 0.2.2 (2023-06-21)
54 | ------------------
55 |
56 | 0.2.1 (2023-06-21)
57 | ------------------
58 | * Fix master and driver lifecycle
59 | * Fix QoS build warning in canopen_core
60 | * Use consistenlty HEX output for NodeID and Index.
61 | * Contributors: Christoph Hellmann Santos, Denis Štogl, Vishnuprasad Prachandabhanu
62 |
63 | 0.2.0 (2023-06-14)
64 | ------------------
65 | * Created package
66 | * Contributors: Aulon Bajrami, Borong Yuan, Błażej Sowa, Christoph Hellmann Santos, Denis Štogl, Lovro, Vishnuprasad Prachandabhanu
67 |
--------------------------------------------------------------------------------
/canopen_core/ConfigExtras.cmake:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2023 Vishnuprasad Prachandabhanu
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 | find_package(Boost REQUIRED system thread)
16 |
--------------------------------------------------------------------------------
/canopen_core/include/canopen_core/device_container_error.hpp:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Christoph Hellmann Santos
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 | #ifndef DEVICE_CONTAINER_ERROR_HPP_
16 | #define DEVICE_CONTAINER_ERROR_HPP_
17 |
18 | #include
19 | #include
20 |
21 | namespace ros2_canopen
22 | {
23 |
24 | /**
25 | * @brief Device Container Exception
26 | *
27 | * This exception is used, when the device container
28 | * fails.
29 | *
30 | */
31 | class DeviceContainerException : public std::exception
32 | {
33 | private:
34 | std::string what_;
35 |
36 | public:
37 | DeviceContainerException(std::string what) { what_ = what; }
38 |
39 | char * what();
40 | };
41 |
42 | } // namespace ros2_canopen
43 |
44 | #endif
45 |
--------------------------------------------------------------------------------
/canopen_core/include/canopen_core/driver_error.hpp:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Christoph Hellmann Santos
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 | #ifndef DRIVER_ERROR_HPP_
16 | #define DRIVER_ERROR_HPP_
17 |
18 | #include
19 | #include
20 |
21 | namespace ros2_canopen
22 | {
23 | /**
24 | * @brief Driver Exception
25 | *
26 | * This exception is used, when a driver
27 | * fails.
28 | *
29 | */
30 | class DriverException : public std::exception
31 | {
32 | private:
33 | std::string what_;
34 |
35 | public:
36 | DriverException(std::string what) { what_ = what; }
37 |
38 | char * what();
39 | };
40 |
41 | } // namespace ros2_canopen
42 |
43 | #endif
44 |
--------------------------------------------------------------------------------
/canopen_core/include/canopen_core/master_error.hpp:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Christoph Hellmann Santos
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 | #ifndef MASTER_ERROR_HPP_
16 | #define MASTER_ERROR_HPP_
17 |
18 | #include
19 |
20 | namespace ros2_canopen
21 | {
22 | /**
23 | * @brief Master Exception
24 | *
25 | * This exception is used, when a master
26 | * fails.
27 | *
28 | */
29 | class MasterException : public std::exception
30 | {
31 | private:
32 | std::string what_;
33 |
34 | public:
35 | MasterException(std::string what) { what_ = what; }
36 |
37 | char * what();
38 | };
39 | } // namespace ros2_canopen
40 |
41 | #endif
42 |
--------------------------------------------------------------------------------
/canopen_core/include/canopen_core/visibility_control.h:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Christoph Hellmann Santos
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 | #ifndef CANOPEN_CORE__VISIBILITY_CONTROL_H_
15 | #define CANOPEN_CORE__VISIBILITY_CONTROL_H_
16 |
17 | // This logic was borrowed (then namespaced) from the examples on the gcc wiki:
18 | // https://gcc.gnu.org/wiki/Visibility
19 |
20 | #if defined _WIN32 || defined __CYGWIN__
21 | #ifdef __GNUC__
22 | #define CANOPEN_CORE_EXPORT __attribute__((dllexport))
23 | #define CANOPEN_CORE_IMPORT __attribute__((dllimport))
24 | #else
25 | #define CANOPEN_CORE_EXPORT __declspec(dllexport)
26 | #define CANOPEN_CORE_IMPORT __declspec(dllimport)
27 | #endif
28 | #ifdef CANOPEN_CORE_BUILDING_LIBRARY
29 | #define CANOPEN_CORE_PUBLIC CANOPEN_CORE_EXPORT
30 | #else
31 | #define CANOPEN_CORE_PUBLIC CANOPEN_CORE_IMPORT
32 | #endif
33 | #define CANOPEN_CORE_PUBLIC_TYPE CANOPEN_CORE_PUBLIC
34 | #define CANOPEN_CORE_LOCAL
35 | #else
36 | #define CANOPEN_CORE_EXPORT __attribute__((visibility("default")))
37 | #define CANOPEN_CORE_IMPORT
38 | #if __GNUC__ >= 4
39 | #define CANOPEN_CORE_PUBLIC __attribute__((visibility("default")))
40 | #define CANOPEN_CORE_LOCAL __attribute__((visibility("hidden")))
41 | #else
42 | #define CANOPEN_CORE_PUBLIC
43 | #define CANOPEN_CORE_LOCAL
44 | #endif
45 | #define CANOPEN_CORE_PUBLIC_TYPE
46 | #endif
47 |
48 | #endif // CANOPEN_CORE__VISIBILITY_CONTROL_H_
49 |
--------------------------------------------------------------------------------
/canopen_core/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | canopen_core
5 | 0.3.0
6 | Core ros2_canopen functionalities such as DeviceContainer and master
7 | Christoph Hellmann Santos
8 | Apache-2.0
9 |
10 | ament_cmake
11 |
12 | canopen_interfaces
13 | lely_core_libraries
14 | lifecycle_msgs
15 | rclcpp
16 | rclcpp_components
17 | rclcpp_lifecycle
18 | yaml_cpp_vendor
19 | boost
20 |
21 | ament_lint_auto
22 |
23 |
24 | ament_cmake
25 |
26 |
27 |
--------------------------------------------------------------------------------
/canopen_core/scripts/setup_vcan.sh:
--------------------------------------------------------------------------------
1 | modprobe vcan
2 | ip link add dev vcan0 type vcan
3 | ip link set up vcan0
4 |
--------------------------------------------------------------------------------
/canopen_core/src/configuration_manager.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Christoph Hellmann Santos
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 "canopen_core/configuration_manager.hpp"
16 | #include
17 |
18 | namespace ros2_canopen
19 | {
20 |
21 | void ConfigurationManager::init_config()
22 | {
23 | std::string dcf_path = "";
24 | for (YAML::const_iterator it = root_.begin(); it != root_.end(); it++)
25 | {
26 | std::string driver_name = it->first.as();
27 | if (driver_name != "options") continue;
28 | YAML::Node config_node = it->second;
29 | if (config_node["dcf_path"])
30 | {
31 | dcf_path = config_node["dcf_path"].as();
32 | }
33 | }
34 |
35 | for (YAML::const_iterator it = root_.begin(); it != root_.end(); it++)
36 | {
37 | std::string driver_name = it->first.as();
38 | if (driver_name == "options") continue;
39 | YAML::Node config_node = it->second;
40 | if (!config_node["dcf_path"])
41 | {
42 | config_node["dcf_path"] = dcf_path;
43 | }
44 | devices_.insert({driver_name, config_node});
45 | }
46 | }
47 |
48 | uint32_t ConfigurationManager::get_all_devices(std::vector & devices)
49 | {
50 | uint32_t count = 0;
51 | for (auto it = devices_.begin(); it != devices_.end(); it++)
52 | {
53 | devices.emplace_back(it->first);
54 | count++;
55 | }
56 | return count;
57 | }
58 |
59 | } // namespace ros2_canopen
60 |
--------------------------------------------------------------------------------
/canopen_core/src/device_container_error.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Christoph Hellmann Santos
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 "canopen_core/device_container_error.hpp"
16 | #include
17 | namespace ros2_canopen
18 | {
19 |
20 | char * DeviceContainerException::what()
21 | {
22 | char * res = new char[1000];
23 | strcpy(res, what_.c_str());
24 | return res;
25 | }
26 | } // namespace ros2_canopen
27 |
--------------------------------------------------------------------------------
/canopen_core/src/device_container_node.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Harshavadan Deshpande
2 | // Christoph Hellmann Santos
3 | //
4 | // Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | // You may obtain a copy of the License at
7 | //
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | //
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 |
16 | #include "canopen_core/device_container.hpp"
17 |
18 | using namespace ros2_canopen;
19 |
20 | int main(int argc, char const * argv[])
21 | {
22 | rclcpp::init(argc, argv);
23 | auto exec = std::make_shared();
24 | auto device_container = std::make_shared(exec);
25 | std::thread spinThread([&device_container]() { device_container->init(); });
26 | exec->add_node(device_container);
27 | exec->spin();
28 | spinThread.join();
29 | device_container->shutdown();
30 | rclcpp::shutdown();
31 | return 0;
32 | }
33 |
--------------------------------------------------------------------------------
/canopen_core/src/driver_error.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Christoph Hellmann Santos
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 "canopen_core/driver_error.hpp"
16 | #include
17 | namespace ros2_canopen
18 | {
19 | char * DriverException::what()
20 | {
21 | char * res = new char[1000];
22 | strcpy(res, what_.c_str());
23 | return res;
24 | }
25 | } // namespace ros2_canopen
26 |
--------------------------------------------------------------------------------
/canopen_core/src/master_error.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Christoph Hellmann Santos
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 "canopen_core/master_error.hpp"
16 | #include
17 | namespace ros2_canopen
18 | {
19 |
20 | char * MasterException::what()
21 | {
22 | char * res = new char[1000];
23 | strcpy(res, what_.c_str());
24 | return res;
25 | }
26 | } // namespace ros2_canopen
27 |
--------------------------------------------------------------------------------
/canopen_core/src/node_interfaces/node_canopen_master.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Christoph Hellmann Santos
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 "canopen_core/node_interfaces/node_canopen_master.hpp"
16 |
17 | template class ros2_canopen::node_interfaces::NodeCanopenMaster;
18 | template class ros2_canopen::node_interfaces::NodeCanopenMaster;
19 |
--------------------------------------------------------------------------------
/canopen_core/test/bus_configs/bad_driver_duplicate.yml:
--------------------------------------------------------------------------------
1 | ---
2 | proxy_device_1:
3 | node_id: 2
4 | dcf: "simple.eds"
5 | dcf_path: "install/canopen_tests/share/canopen_tests/config/simple"
6 | driver: "ros2_canopen::CanopenDriver"
7 | package: "canopen_core"
8 |
9 | proxy_device_1:
10 | node_id: 2
11 | dcf: "simple.eds"
12 | dcf_path: "install/canopen_tests/share/canopen_tests/config/simple"
13 | driver: "ros2_canopen::CanopenDriver"
14 | package: "canopen_core"
15 |
--------------------------------------------------------------------------------
/canopen_core/test/bus_configs/bad_driver_no_driver.yml:
--------------------------------------------------------------------------------
1 | ---
2 | proxy_device_1:
3 | node_id: 2
4 | dcf: "simple.eds"
5 | dcf_path: "install/canopen_tests/share/canopen_tests/config/simple"
6 | package: "canopen_core"
7 |
--------------------------------------------------------------------------------
/canopen_core/test/bus_configs/bad_driver_no_id.yml:
--------------------------------------------------------------------------------
1 | ---
2 | proxy_device_1:
3 | dcf: "simple.eds"
4 | dcf_path: "install/canopen_tests/share/canopen_tests/config/simple"
5 | driver: "ros2_canopen::CanopenDriver"
6 | package: "canopen_core"
7 |
--------------------------------------------------------------------------------
/canopen_core/test/bus_configs/bad_driver_no_package.yml:
--------------------------------------------------------------------------------
1 | ---
2 | proxy_device_1:
3 | node_id: 2
4 | dcf: "simple.eds"
5 | dcf_path: "install/canopen_tests/share/canopen_tests/config/simple"
6 | driver: "ros2_canopen::CanopenDriver"
7 |
--------------------------------------------------------------------------------
/canopen_core/test/bus_configs/bad_master_no_driver.yml:
--------------------------------------------------------------------------------
1 | ---
2 | master:
3 | node_id: 1
4 | package: "canopen_core"
5 |
--------------------------------------------------------------------------------
/canopen_core/test/bus_configs/bad_master_no_id.yml:
--------------------------------------------------------------------------------
1 | ---
2 | master:
3 | driver: "ros2_canopen::CanopenMaster"
4 | package: "canopen_core"
5 |
--------------------------------------------------------------------------------
/canopen_core/test/bus_configs/bad_master_no_package.yml:
--------------------------------------------------------------------------------
1 | ---
2 | master:
3 | node_id: 1
4 | driver: "ros2_canopen::CanopenMaster"
5 |
--------------------------------------------------------------------------------
/canopen_core/test/bus_configs/bad_no_master.yml:
--------------------------------------------------------------------------------
1 | ---
2 | proxy_device_1:
3 | node_id: 2
4 | dcf: "simple.eds"
5 | dcf_path: "install/canopen_tests/share/canopen_tests/config/simple"
6 | driver: "ros2_canopen::CanopenDriver"
7 | package: "canopen_core"
8 |
9 | proxy_device_2:
10 | node_id: 3
11 | dcf: "simple.eds"
12 | dcf_path: "install/canopen_tests/share/canopen_tests/config/simple"
13 | driver: "ros2_canopen::CanopenDriver"
14 | package: "canopen_core"
15 |
--------------------------------------------------------------------------------
/canopen_core/test/bus_configs/good_driver.yml:
--------------------------------------------------------------------------------
1 | ---
2 | proxy_device_1:
3 | node_id: 2
4 | dcf: "simple.eds"
5 | dcf_path: "install/canopen_tests/share/canopen_tests/config/simple"
6 | driver: "ros2_canopen::CanopenDriver"
7 | package: "canopen_core"
8 |
--------------------------------------------------------------------------------
/canopen_core/test/bus_configs/good_master.yml:
--------------------------------------------------------------------------------
1 | ---
2 | master:
3 | node_id: 1
4 | driver: "ros2_canopen::CanopenMaster"
5 | package: "canopen_core"
6 |
--------------------------------------------------------------------------------
/canopen_core/test/bus_configs/good_master_and_two_driver.yml:
--------------------------------------------------------------------------------
1 | ---
2 | master:
3 | node_id: 1
4 | driver: "ros2_canopen::CanopenMaster"
5 | package: "canopen_core"
6 |
7 | proxy_device_1:
8 | node_id: 2
9 | dcf: "simple.eds"
10 | dcf_path: "install/canopen_tests/share/canopen_tests/config/simple"
11 | driver: "ros2_canopen::CanopenDriver"
12 | package: "canopen_core"
13 |
14 | proxy_device_2:
15 | node_id: 3
16 | dcf: "simple.eds"
17 | dcf_path: "install/canopen_tests/share/canopen_tests/config/simple"
18 | driver: "ros2_canopen::CanopenDriver"
19 | package: "canopen_core"
20 |
--------------------------------------------------------------------------------
/canopen_core/test/test_errors.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Christoph Hellmann Santos
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 "canopen_core/device_container_error.hpp"
17 | #include "canopen_core/driver_error.hpp"
18 | #include "canopen_core/master_error.hpp"
19 | #include "gmock/gmock.h"
20 | #include "gtest/gtest.h"
21 | using namespace std::chrono_literals;
22 | using namespace ros2_canopen;
23 | using namespace testing;
24 |
25 | TEST(DriverErrorTest, test_what)
26 | {
27 | DriverException test_obj("hello");
28 | EXPECT_TRUE(std::string("hello").compare(test_obj.what()) == 0);
29 | }
30 |
31 | TEST(MasterErrorTest, test_what)
32 | {
33 | MasterException test_obj("hello");
34 | EXPECT_TRUE(std::string("hello").compare(test_obj.what()) == 0);
35 | }
36 |
37 | TEST(DeviceContainerErrorTest, test_what)
38 | {
39 | DeviceContainerException test_obj("hello");
40 | EXPECT_TRUE(std::string("hello").compare(test_obj.what()) == 0);
41 | }
42 |
--------------------------------------------------------------------------------
/canopen_fake_slaves/CHANGELOG.rst:
--------------------------------------------------------------------------------
1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 | Changelog for package canopen_fake_slaves
3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4 |
5 | 0.2.9 (2024-04-16)
6 | ------------------
7 |
8 | 0.3.0 (2024-12-12)
9 | ------------------
10 | * fix loop timer for run_velocity_mode
11 | * Fix clang format
12 | * Add comments for the fake slave function
13 | * Fix the thread issue.
14 | * Apply suggestions from code review
15 | Co-authored-by: Dr. Denis
16 | * Working version.
17 | * Periodic messages sent, but not received properly.
18 | * Working logic. Still have to work on the edf file.
19 | * Put the periodic messages in OnWrite
20 | * Extend fake_slaves to publish messages via rpdo
21 |
22 | 0.2.12 (2024-04-22)
23 | -------------------
24 | * Merge pull request `#265 `_ from kurtist123/feature/expose-fake-slave-includes
25 | build: export include directories
26 | * build: export include directories
27 | * 0.2.9
28 | * forthcoming
29 | * Contributors: Kurtis Thrush, Vishnuprasad Prachandabhanu, ipa-vsp
30 |
31 | 0.2.8 (2024-01-19)
32 | ------------------
33 | * Add fake profile velocity (`#230 `_)
34 | * Add simple sequence homing emulation
35 | * Add fake velocity mode
36 | * Formatting
37 | ---------
38 | * Add simple sequence homing emulation (`#229 `_)
39 | * Contributors: Christoph Hellmann Santos
40 |
41 | 0.2.7 (2023-06-30)
42 | ------------------
43 | * Add missing license headers and activate ament_copyright
44 | * Contributors: Christoph Hellmann Santos
45 |
46 | 0.2.6 (2023-06-24)
47 | ------------------
48 |
49 | 0.2.5 (2023-06-23)
50 | ------------------
51 |
52 | 0.2.4 (2023-06-22)
53 | ------------------
54 |
55 | 0.2.3 (2023-06-22)
56 | ------------------
57 |
58 | 0.2.2 (2023-06-21)
59 | ------------------
60 |
61 | 0.2.1 (2023-06-21)
62 | ------------------
63 | * Fix fake slave for PDOs
64 | * Contributors: Christoph Hellmann Santos
65 |
66 | 0.2.0 (2023-06-14)
67 | ------------------
68 | * Created package
69 | * Contributors: Błażej Sowa, Christoph Hellmann Santos, James Ward, Vishnuprasad Prachandabhanu
70 |
--------------------------------------------------------------------------------
/canopen_fake_slaves/Readme.md:
--------------------------------------------------------------------------------
1 | # CANopen Mock Slaves
2 |
3 | ## Motion Controller Slaves
4 |
5 | Supported modes:
6 | * Cyclic Position
7 | * Profiled Position (Thanks to motion generator https://github.com/EFeru/MotionGenerator)
8 | * Interpolated Position
9 | * Homing
10 | * Profiled Velocity
11 |
--------------------------------------------------------------------------------
/canopen_fake_slaves/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | canopen_fake_slaves
5 | 0.3.0
6 | Package with mock canopen slave
7 | Christoph Hellmann Santos
8 | Apache-2.0
9 |
10 | ament_cmake
11 |
12 | lely_core_libraries
13 | lifecycle_msgs
14 | rclcpp
15 | rclcpp_lifecycle
16 |
17 | ament_lint_auto
18 |
19 |
20 | ament_cmake
21 |
22 |
23 |
--------------------------------------------------------------------------------
/canopen_fake_slaves/src/basic_slave.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Christoph Hellmann Santos
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 "canopen_fake_slaves/basic_slave.hpp"
16 | #include "rclcpp/rclcpp.hpp"
17 |
18 | int main(int argc, char * argv[])
19 | {
20 | rclcpp::InitOptions options;
21 | options.shutdown_on_signal = true;
22 | rclcpp::init(argc, argv, options, rclcpp::SignalHandlerOptions::All);
23 | rclcpp::executors::SingleThreadedExecutor executor;
24 | auto canopen_slave = std::make_shared("basic_slave");
25 | executor.add_node(canopen_slave->get_node_base_interface());
26 | executor.spin();
27 | return 0;
28 | }
29 |
--------------------------------------------------------------------------------
/canopen_fake_slaves/src/cia402_slave.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Christoph Hellmann Santos
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 "canopen_fake_slaves/cia402_slave.hpp"
16 | #include "rclcpp/rclcpp.hpp"
17 |
18 | int main(int argc, char * argv[])
19 | {
20 | rclcpp::init(argc, argv);
21 | rclcpp::executors::SingleThreadedExecutor executor;
22 | auto canopen_slave = std::make_shared("cia402_slave");
23 | executor.add_node(canopen_slave->get_node_base_interface());
24 | executor.spin();
25 | rclcpp::shutdown();
26 | return 0;
27 | }
28 |
--------------------------------------------------------------------------------
/canopen_interfaces/CHANGELOG.rst:
--------------------------------------------------------------------------------
1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 | Changelog for package canopen_interfaces
3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4 |
5 | 0.2.9 (2024-04-16)
6 | ------------------
7 |
8 | 0.3.0 (2024-12-12)
9 | ------------------
10 |
11 | 0.2.12 (2024-04-22)
12 | -------------------
13 | * 0.2.9
14 | * forthcoming
15 | * Contributors: ipa-vsp
16 |
17 | 0.2.8 (2024-01-19)
18 | ------------------
19 |
20 | 0.2.7 (2023-06-30)
21 | ------------------
22 |
23 | 0.2.6 (2023-06-24)
24 | ------------------
25 |
26 | 0.2.5 (2023-06-23)
27 | ------------------
28 |
29 | 0.2.4 (2023-06-22)
30 | ------------------
31 |
32 | 0.2.3 (2023-06-22)
33 | ------------------
34 |
35 | 0.2.2 (2023-06-21)
36 | ------------------
37 |
38 | 0.2.1 (2023-06-21)
39 | ------------------
40 |
41 | 0.2.0 (2023-06-14)
42 | ------------------
43 | * Created package
44 | * Contributors: Błażej Sowa, Christoph Hellmann Santos, Denis Štogl, Lovro
45 |
--------------------------------------------------------------------------------
/canopen_interfaces/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.8)
2 | project(canopen_interfaces)
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(rosidl_default_generators REQUIRED)
11 | # uncomment the following section in order to fill in
12 | # further dependencies manually.
13 | # find_package( REQUIRED)
14 |
15 | rosidl_generate_interfaces(${PROJECT_NAME}
16 | "srv/COHeartbeatID.srv"
17 | "srv/CONmtID.srv"
18 | "srv/CORead.srv"
19 | "srv/COReadID.srv"
20 | "srv/COWrite.srv"
21 | "srv/COWriteID.srv"
22 | "srv/COTargetDouble.srv"
23 | "srv/CONode.srv"
24 | "msg/COData.msg"
25 | )
26 |
27 |
28 | if(BUILD_TESTING)
29 | find_package(ament_lint_auto REQUIRED)
30 | # the following line skips the linter which checks for copyrights
31 | # uncomment the line when a copyright and license is not present in all source files
32 | #set(ament_cmake_copyright_FOUND TRUE)
33 | # the following line skips cpplint (only works in a git repo)
34 | # uncomment the line when this package is not in a git repo
35 | #set(ament_cmake_cpplint_FOUND TRUE)
36 | ament_lint_auto_find_test_dependencies()
37 | endif()
38 |
39 | ament_package()
40 |
--------------------------------------------------------------------------------
/canopen_interfaces/msg/COData.msg:
--------------------------------------------------------------------------------
1 | uint16 index
2 | uint8 subindex
3 | uint32 data
4 |
--------------------------------------------------------------------------------
/canopen_interfaces/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | canopen_interfaces
5 | 0.3.0
6 | Services and Messages for ros2_canopen stack
7 | Christoph Hellmann Santos
8 | Apache-2.0
9 |
10 | ament_cmake
11 |
12 | ament_lint_auto
13 | ament_lint_common
14 | rosidl_default_generators
15 | rosidl_default_runtime
16 | rosidl_interface_packages
17 |
18 | ament_cmake
19 |
20 |
21 |
--------------------------------------------------------------------------------
/canopen_interfaces/srv/COHeartbeatID.srv:
--------------------------------------------------------------------------------
1 | uint8 nodeid
2 | uint16 heartbeat #ms
3 | ---
4 | bool success
5 |
--------------------------------------------------------------------------------
/canopen_interfaces/srv/CONmtID.srv:
--------------------------------------------------------------------------------
1 | uint8 nmtcommand
2 | uint8 nodeid
3 | ---
4 | bool success
5 |
--------------------------------------------------------------------------------
/canopen_interfaces/srv/CONode.srv:
--------------------------------------------------------------------------------
1 | uint8 nodeid
2 | ---
3 | bool success
4 |
--------------------------------------------------------------------------------
/canopen_interfaces/srv/CORead.srv:
--------------------------------------------------------------------------------
1 | uint16 index
2 | uint8 subindex
3 | ---
4 | bool success
5 | uint32 data
6 |
--------------------------------------------------------------------------------
/canopen_interfaces/srv/COReadID.srv:
--------------------------------------------------------------------------------
1 | uint8 CANOPEN_DATATYPE_INT8 = 0x02
2 | uint8 CANOPEN_DATATYPE_INT16 = 0x03
3 | uint8 CANOPEN_DATATYPE_INT32 = 0x04
4 | uint8 CANOPEN_DATATYPE_UINT8 = 0x05
5 | uint8 CANOPEN_DATATYPE_UINT16 = 0x06
6 | uint8 CANOPEN_DATATYPE_UINT32 = 0x07
7 |
8 | uint8 nodeid
9 | uint16 index
10 | uint8 subindex
11 | # 8 = uint8_t, 16 = uint16_t, 32 = uint32_t
12 | uint8 canopen_datatype
13 | ---
14 | bool success
15 | uint32 data
16 |
--------------------------------------------------------------------------------
/canopen_interfaces/srv/COTargetDouble.srv:
--------------------------------------------------------------------------------
1 | float64 target
2 | ---
3 | bool success
4 |
--------------------------------------------------------------------------------
/canopen_interfaces/srv/COWrite.srv:
--------------------------------------------------------------------------------
1 | uint16 index
2 | uint8 subindex
3 | uint32 data
4 | ---
5 | bool success
6 |
--------------------------------------------------------------------------------
/canopen_interfaces/srv/COWriteID.srv:
--------------------------------------------------------------------------------
1 | uint8 CANOPEN_DATATYPE_INT8 = 0x02
2 | uint8 CANOPEN_DATATYPE_INT16 = 0x03
3 | uint8 CANOPEN_DATATYPE_INT32 = 0x04
4 | uint8 CANOPEN_DATATYPE_UINT8 = 0x05
5 | uint8 CANOPEN_DATATYPE_UINT16 = 0x06
6 | uint8 CANOPEN_DATATYPE_UINT32 = 0x07
7 |
8 | int8 nodeid
9 | uint16 index
10 | uint8 subindex
11 | uint32 data
12 | # 8 = uint8_t, 16 = uint16_t, 32 = uint32_t
13 | uint8 canopen_datatype
14 | ---
15 | bool success
16 |
--------------------------------------------------------------------------------
/canopen_master_driver/CHANGELOG.rst:
--------------------------------------------------------------------------------
1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 | Changelog for package canopen_master_driver
3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4 |
5 | 0.2.9 (2024-04-16)
6 | ------------------
7 | * Add timeouts
8 | * Contributors: Vishnuprasad Prachandabhanu
9 |
10 | 0.3.0 (2024-12-12)
11 | ------------------
12 |
13 | 0.2.12 (2024-04-22)
14 | -------------------
15 | * 0.2.9
16 | * forthcoming
17 | * Merge pull request `#220 `_ from ipa-vsp/feature/timeout-config
18 | Add timeouts
19 | * Revert timeout change to master since I'm not providing a way to set that timeout.
20 | * Make 20ms a default argument of the master & driver bridges.
21 | * timeout for booting slave
22 | * Contributors: Gerry Salinas, Vishnuprasad Prachandabhanu, ipa-vsp
23 |
24 | 0.2.8 (2024-01-19)
25 | ------------------
26 |
27 | 0.2.7 (2023-06-30)
28 | ------------------
29 | * Add missing license headers and activate ament_copyright
30 | * Contributors: Christoph Hellmann Santos
31 |
32 | 0.2.6 (2023-06-24)
33 | ------------------
34 |
35 | 0.2.5 (2023-06-23)
36 | ------------------
37 |
38 | 0.2.4 (2023-06-22)
39 | ------------------
40 |
41 | 0.2.3 (2023-06-22)
42 | ------------------
43 |
44 | 0.2.2 (2023-06-21)
45 | ------------------
46 |
47 | 0.2.1 (2023-06-21)
48 | ------------------
49 | * Fix master lifecycle
50 | * Contributors: Christoph Hellmann Santos
51 |
52 | 0.2.0 (2023-06-14)
53 | ------------------
54 | * Created package
55 | * Contributors: Błażej Sowa, Christoph Hellmann Santos
56 |
--------------------------------------------------------------------------------
/canopen_master_driver/include/canopen_master_driver/lifecycle_master_driver.hpp:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Harshavadan Deshpande
2 | // Christoph Hellmann Santos
3 | //
4 | // Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | // You may obtain a copy of the License at
7 | //
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | //
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 | #ifndef LIFECYCLE_MASTER_DRIVER_HPP
16 | #define LIFECYCLE_MASTER_DRIVER_HPP
17 |
18 | #include
19 | #include
20 | #include
21 |
22 | #include "canopen_core/master_node.hpp"
23 | #include "canopen_master_driver/node_interfaces/node_canopen_basic_master.hpp"
24 |
25 | namespace ros2_canopen
26 | {
27 | /**
28 | * @brief Lifecycle Master Node
29 | *
30 | * This class implements the Lifecycle master interface.
31 | * It uses the Lely Master Bridge and exposes a ROS node
32 | * interface.
33 | *
34 | */
35 | class LifecycleMasterDriver : public ros2_canopen::LifecycleCanopenMaster
36 | {
37 | std::shared_ptr>
38 | node_canopen_basic_master_;
39 |
40 | public:
41 | explicit LifecycleMasterDriver(const rclcpp::NodeOptions & node_options);
42 | };
43 |
44 | } // namespace ros2_canopen
45 |
46 | #endif
47 |
--------------------------------------------------------------------------------
/canopen_master_driver/include/canopen_master_driver/master_driver.hpp:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Harshavadan Deshpande
2 | // Christoph Hellmann Santos
3 | //
4 | // Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | // You may obtain a copy of the License at
7 | //
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | //
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 | #ifndef MASTER_DRIVER_HPP
16 | #define MASTER_DRIVER_HPP
17 |
18 | #include "canopen_core/master_node.hpp"
19 | #include "canopen_master_driver/node_interfaces/node_canopen_basic_master.hpp"
20 |
21 | namespace ros2_canopen
22 | {
23 | /**
24 | * @brief Master Node
25 | *
26 | * This class implements the Lifecycle master interface.
27 | * It uses the Lely Master Bridge and exposes a ROS node
28 | * interface.
29 | *
30 | */
31 | class MasterDriver : public ros2_canopen::CanopenMaster
32 | {
33 | std::shared_ptr> node_canopen_basic_master_;
34 |
35 | public:
36 | explicit MasterDriver(const rclcpp::NodeOptions & node_options);
37 | };
38 |
39 | } // namespace ros2_canopen
40 |
41 | #endif
42 |
--------------------------------------------------------------------------------
/canopen_master_driver/include/canopen_master_driver/visibility_control.h:
--------------------------------------------------------------------------------
1 | // Copyright 2023 ROS-Industrial
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 | #ifndef CANOPEN_MASTER_DRIVER__VISIBILITY_CONTROL_H_
16 | #define CANOPEN_MASTER_DRIVER__VISIBILITY_CONTROL_H_
17 |
18 | // This logic was borrowed (then namespaced) from the examples on the gcc wiki:
19 | // https://gcc.gnu.org/wiki/Visibility
20 |
21 | #if defined _WIN32 || defined __CYGWIN__
22 | #ifdef __GNUC__
23 | #define CANOPEN_MASTER_DRIVER_EXPORT __attribute__((dllexport))
24 | #define CANOPEN_MASTER_DRIVER_IMPORT __attribute__((dllimport))
25 | #else
26 | #define CANOPEN_MASTER_DRIVER_EXPORT __declspec(dllexport)
27 | #define CANOPEN_MASTER_DRIVER_IMPORT __declspec(dllimport)
28 | #endif
29 | #ifdef CANOPEN_MASTER_DRIVER_BUILDING_LIBRARY
30 | #define CANOPEN_MASTER_DRIVER_PUBLIC CANOPEN_MASTER_DRIVER_EXPORT
31 | #else
32 | #define CANOPEN_MASTER_DRIVER_PUBLIC CANOPEN_MASTER_DRIVER_IMPORT
33 | #endif
34 | #define CANOPEN_MASTER_DRIVER_PUBLIC_TYPE CANOPEN_MASTER_DRIVER_PUBLIC
35 | #define CANOPEN_MASTER_DRIVER_LOCAL
36 | #else
37 | #define CANOPEN_MASTER_DRIVER_EXPORT __attribute__((visibility("default")))
38 | #define CANOPEN_MASTER_DRIVER_IMPORT
39 | #if __GNUC__ >= 4
40 | #define CANOPEN_MASTER_DRIVER_PUBLIC __attribute__((visibility("default")))
41 | #define CANOPEN_MASTER_DRIVER_LOCAL __attribute__((visibility("hidden")))
42 | #else
43 | #define CANOPEN_MASTER_DRIVER_PUBLIC
44 | #define CANOPEN_MASTER_DRIVER_LOCAL
45 | #endif
46 | #define CANOPEN_MASTER_DRIVER_PUBLIC_TYPE
47 | #endif
48 |
49 | #endif // CANOPEN_MASTER_DRIVER__VISIBILITY_CONTROL_H_
50 |
--------------------------------------------------------------------------------
/canopen_master_driver/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | canopen_master_driver
5 | 0.3.0
6 | Basic canopen master implementation
7 | Christoph Hellmann Santos
8 | Apache-2.0
9 |
10 | ament_cmake_ros
11 |
12 | canopen_core
13 | canopen_interfaces
14 | lely_core_libraries
15 | rclcpp
16 | rclcpp_components
17 | rclcpp_lifecycle
18 |
19 | ament_lint_auto
20 | ament_lint_common
21 |
22 |
23 | ament_cmake
24 |
25 |
26 |
--------------------------------------------------------------------------------
/canopen_master_driver/src/lifecycle_master_driver.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Harshavadan Deshpande
2 | // Christoph Hellmann Santos
3 | //
4 | // Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | // You may obtain a copy of the License at
7 | //
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | //
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 |
16 | #include "canopen_master_driver/lifecycle_master_driver.hpp"
17 |
18 | namespace ros2_canopen
19 | {
20 |
21 | ros2_canopen::LifecycleMasterDriver::LifecycleMasterDriver(const rclcpp::NodeOptions & node_options)
22 | : LifecycleCanopenMaster(node_options)
23 | {
24 | node_canopen_master_ =
25 | std::make_shared>(
26 | this);
27 | }
28 |
29 | } // namespace ros2_canopen
30 |
31 | #include "rclcpp_components/register_node_macro.hpp"
32 | RCLCPP_COMPONENTS_REGISTER_NODE(ros2_canopen::LifecycleMasterDriver)
33 |
--------------------------------------------------------------------------------
/canopen_master_driver/src/master_driver.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Harshavadan Deshpande
2 | // Christoph Hellmann Santos
3 | //
4 | // Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | // You may obtain a copy of the License at
7 | //
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | //
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 |
16 | #include "canopen_master_driver/master_driver.hpp"
17 |
18 | namespace ros2_canopen
19 | {
20 |
21 | ros2_canopen::MasterDriver::MasterDriver(const rclcpp::NodeOptions & node_options)
22 | : CanopenMaster(node_options)
23 | {
24 | node_canopen_basic_master_ =
25 | std::make_shared>(this);
26 | node_canopen_master_ = std::static_pointer_cast(
27 | node_canopen_basic_master_);
28 | }
29 |
30 | } // namespace ros2_canopen
31 |
32 | #include "rclcpp_components/register_node_macro.hpp"
33 | RCLCPP_COMPONENTS_REGISTER_NODE(ros2_canopen::MasterDriver)
34 |
--------------------------------------------------------------------------------
/canopen_master_driver/src/node_interfaces/node_canopen_basic_master.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Harshavadan Deshpande
2 | // Christoph Hellmann Santos
3 | //
4 | // Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | // You may obtain a copy of the License at
7 | //
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | //
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 |
16 | #include "canopen_master_driver/node_interfaces/node_canopen_basic_master.hpp"
17 | #include "canopen_master_driver/node_interfaces/node_canopen_basic_master_impl.hpp"
18 |
19 | using namespace ros2_canopen::node_interfaces;
20 |
21 | template class ros2_canopen::node_interfaces::NodeCanopenBasicMaster;
22 | template class ros2_canopen::node_interfaces::NodeCanopenBasicMaster<
23 | rclcpp_lifecycle::LifecycleNode>;
24 |
--------------------------------------------------------------------------------
/canopen_master_driver/test/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | ament_add_gtest(test_node_canopen_basic_driver
2 | test_node_canopen_basic_master.cpp
3 | )
4 | ament_target_dependencies(test_node_canopen_basic_driver
5 | ${dependencies}
6 | )
7 | target_include_directories(test_node_canopen_basic_driver PUBLIC
8 | ${CMAKE_CURRENT_SOURCE_DIR}/../include/
9 | )
10 | target_link_libraries(test_node_canopen_basic_driver
11 | master_driver
12 | node_canopen_basic_master
13 | lely_master_bridge
14 | )
15 |
16 | ament_add_gtest(test_node_canopen_basic_driver_ros
17 | test_node_canopen_basic_master_ros.cpp
18 | )
19 | ament_target_dependencies(test_node_canopen_basic_driver_ros
20 | ${dependencies}
21 | )
22 | target_include_directories(test_node_canopen_basic_driver_ros PUBLIC
23 | ${CMAKE_CURRENT_SOURCE_DIR}/../include/
24 | )
25 | target_link_libraries(test_node_canopen_basic_driver_ros
26 | master_driver
27 | node_canopen_basic_master
28 | lely_master_bridge
29 | )
30 |
31 | ament_add_gtest(test_master_driver_component
32 | test_master_driver_component.cpp
33 | )
34 | ament_target_dependencies(test_master_driver_component
35 | ${dependencies}
36 | )
37 | target_include_directories(test_master_driver_component PUBLIC
38 | ${CMAKE_CURRENT_SOURCE_DIR}/../include/
39 | )
40 | target_link_libraries(test_master_driver_component
41 | master_driver
42 | lifecycle_master_driver
43 | lely_master_bridge
44 | )
45 |
46 | file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/master.dcf DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
47 |
--------------------------------------------------------------------------------
/canopen_master_driver/test/test_master_driver_component.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Christoph Hellmann Santos
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 "canopen_master_driver/node_interfaces/node_canopen_basic_master.hpp"
21 | #include "gtest/gtest.h"
22 | using namespace rclcpp_components;
23 |
24 | TEST(MasterDriverComponent, test_load_lifecycle_master_driver)
25 | {
26 | rclcpp::init(0, nullptr);
27 | auto exec = std::make_shared();
28 | auto manager = std::make_shared(exec);
29 |
30 | std::vector resources =
31 | manager->get_component_resources("canopen_master_driver");
32 |
33 | EXPECT_EQ(2u, resources.size());
34 |
35 | auto factory = manager->create_component_factory(resources[0]);
36 | auto instance_wrapper =
37 | factory->create_node_instance(rclcpp::NodeOptions().use_global_arguments(false));
38 |
39 | rclcpp::shutdown();
40 | }
41 |
42 | TEST(MasterDriverComponent, test_load_master_driver)
43 | {
44 | rclcpp::init(0, nullptr);
45 | auto exec = std::make_shared();
46 | auto manager = std::make_shared(exec);
47 |
48 | std::vector resources =
49 | manager->get_component_resources("canopen_master_driver");
50 |
51 | EXPECT_EQ(2u, resources.size());
52 |
53 | auto factory = manager->create_component_factory(resources[1]);
54 | auto instance_wrapper =
55 | factory->create_node_instance(rclcpp::NodeOptions().use_global_arguments(false));
56 |
57 | rclcpp::shutdown();
58 | }
59 |
--------------------------------------------------------------------------------
/canopen_master_driver/test/test_node_canopen_basic_master.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Christoph Hellmann Santos
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 "canopen_master_driver/node_interfaces/node_canopen_basic_master.hpp"
16 | #include "gtest/gtest.h"
17 |
18 | class RclCppFixture
19 | {
20 | public:
21 | RclCppFixture()
22 | {
23 | rclcpp::init(0, nullptr);
24 | node = new rclcpp::Node("Node");
25 | interface = new ros2_canopen::node_interfaces::NodeCanopenBasicMaster(node);
26 | }
27 | virtual ~RclCppFixture()
28 | {
29 | rclcpp::shutdown();
30 | delete (interface);
31 | delete (node);
32 | }
33 |
34 | rclcpp::Node * node;
35 | ros2_canopen::node_interfaces::NodeCanopenBasicMaster * interface;
36 | };
37 | RclCppFixture g_rclcppfixture;
38 |
39 | TEST(NodeCanopenBasicMaster, test_bad_sequence_configure)
40 | {
41 | auto iface = static_cast(
42 | g_rclcppfixture.interface);
43 | EXPECT_ANY_THROW(iface->configure());
44 | }
45 |
46 | TEST(NodeCanopenBasicMaster, test_bad_sequence_activate)
47 | {
48 | auto iface = static_cast(
49 | g_rclcppfixture.interface);
50 | EXPECT_ANY_THROW(iface->activate());
51 | }
52 |
53 | TEST(NodeCanopenBasicMaster, test_good_sequence)
54 | {
55 | auto iface = static_cast(
56 | g_rclcppfixture.interface);
57 | try
58 | {
59 | iface->init();
60 | }
61 | catch (const std::exception & e)
62 | {
63 | RCLCPP_ERROR(rclcpp::get_logger("test"), e.what());
64 | }
65 | EXPECT_NO_THROW(iface->configure());
66 | }
67 |
--------------------------------------------------------------------------------
/canopen_proxy_driver/CHANGELOG.rst:
--------------------------------------------------------------------------------
1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 | Changelog for package canopen_proxy_driver
3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4 |
5 | 0.2.9 (2024-04-16)
6 | ------------------
7 |
8 | 0.3.0 (2024-12-12)
9 | ------------------
10 |
11 | 0.2.12 (2024-04-22)
12 | -------------------
13 | * 0.2.9
14 | * forthcoming
15 | * Contributors: ipa-vsp
16 |
17 | 0.2.8 (2024-01-19)
18 | ------------------
19 |
20 | 0.2.7 (2023-06-30)
21 | ------------------
22 | * Add missing license headers and activate ament_copyright
23 | * Fix maintainer naming
24 | * Contributors: Christoph Hellmann Santos
25 |
26 | 0.2.6 (2023-06-24)
27 | ------------------
28 |
29 | 0.2.5 (2023-06-23)
30 | ------------------
31 |
32 | 0.2.4 (2023-06-22)
33 | ------------------
34 |
35 | 0.2.3 (2023-06-22)
36 | ------------------
37 |
38 | 0.2.2 (2023-06-21)
39 | ------------------
40 |
41 | 0.2.1 (2023-06-21)
42 | ------------------
43 | * Use consistenlty (uppercase) HEX output for NodeID and Index.
44 | * Contributors: Christoph Hellmann Santos, Denis Štogl
45 |
46 | 0.2.0 (2023-06-14)
47 | ------------------
48 | * Created package
49 | * Contributors: Błażej Sowa, Christoph Hellmann Santos, Denis Štogl, Lovro, Vishnuprasad Prachandabhanu
50 |
--------------------------------------------------------------------------------
/canopen_proxy_driver/include/canopen_proxy_driver/visibility_control.h:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Christoph Hellmann Santos
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 | #ifndef CANOPEN_PROXY_DRIVER__VISIBILITY_CONTROL_H_
15 | #define CANOPEN_PROXY_DRIVER__VISIBILITY_CONTROL_H_
16 |
17 | // This logic was borrowed (then namespaced) from the examples on the gcc wiki:
18 | // https://gcc.gnu.org/wiki/Visibility
19 |
20 | #if defined _WIN32 || defined __CYGWIN__
21 | #ifdef __GNUC__
22 | #define CANOPEN_PROXY_DRIVER_EXPORT __attribute__((dllexport))
23 | #define CANOPEN_PROXY_DRIVER_IMPORT __attribute__((dllimport))
24 | #else
25 | #define CANOPEN_PROXY_DRIVER_EXPORT __declspec(dllexport)
26 | #define CANOPEN_PROXY_DRIVER_IMPORT __declspec(dllimport)
27 | #endif
28 | #ifdef CANOPEN_PROXY_DRIVER_BUILDING_LIBRARY
29 | #define CANOPEN_PROXY_DRIVER_PUBLIC CANOPEN_PROXY_DRIVER_EXPORT
30 | #else
31 | #define CANOPEN_PROXY_DRIVER_PUBLIC CANOPEN_PROXY_DRIVER_IMPORT
32 | #endif
33 | #define CANOPEN_PROXY_DRIVER_PUBLIC_TYPE CANOPEN_PROXY_DRIVER_PUBLIC
34 | #define CANOPEN_PROXY_DRIVER_LOCAL
35 | #else
36 | #define CANOPEN_PROXY_DRIVER_EXPORT __attribute__((visibility("default")))
37 | #define CANOPEN_PROXY_DRIVER_IMPORT
38 | #if __GNUC__ >= 4
39 | #define CANOPEN_PROXY_DRIVER_PUBLIC __attribute__((visibility("default")))
40 | #define CANOPEN_PROXY_DRIVER_LOCAL __attribute__((visibility("hidden")))
41 | #else
42 | #define CANOPEN_PROXY_DRIVER_PUBLIC
43 | #define CANOPEN_PROXY_DRIVER_LOCAL
44 | #endif
45 | #define CANOPEN_PROXY_DRIVER_PUBLIC_TYPE
46 | #endif
47 |
48 | #endif // CANOPEN_PROXY_DRIVER__VISIBILITY_CONTROL_H_
49 |
--------------------------------------------------------------------------------
/canopen_proxy_driver/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | canopen_proxy_driver
5 | 0.3.0
6 | Simple proxy driver for the ros2_canopen stack
7 | Christoph Hellmann Santos
8 | Apache-2.0
9 |
10 | ament_cmake_ros
11 |
12 | canopen_base_driver
13 | canopen_core
14 | canopen_interfaces
15 | rclcpp
16 | rclcpp_components
17 | rclcpp_lifecycle
18 | std_msgs
19 | std_srvs
20 |
21 | ament_lint_auto
22 |
23 |
24 | ament_cmake
25 |
26 |
27 |
--------------------------------------------------------------------------------
/canopen_proxy_driver/readme.md:
--------------------------------------------------------------------------------
1 | # canopen_ros_proxy_driver
2 |
3 | ## Testing
4 | ```
5 | colcon test --packages-select canopen_proxy_driver --event-handlers desktop_notification+ status+ summary- console_direct+ terminal_title+
6 | ```
7 |
--------------------------------------------------------------------------------
/canopen_proxy_driver/src/lifecycle_proxy_driver.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Christoph Hellmann Santos
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 "canopen_proxy_driver/lifecycle_proxy_driver.hpp"
15 |
16 | using namespace ros2_canopen;
17 |
18 | LifecycleProxyDriver::LifecycleProxyDriver(rclcpp::NodeOptions node_options)
19 | : LifecycleCanopenDriver(node_options)
20 | {
21 | node_canopen_proxy_driver_ =
22 | std::make_shared>(
23 | this);
24 | node_canopen_driver_ = std::static_pointer_cast(
25 | node_canopen_proxy_driver_);
26 | }
27 |
28 | #include "rclcpp_components/register_node_macro.hpp"
29 | RCLCPP_COMPONENTS_REGISTER_NODE(ros2_canopen::LifecycleProxyDriver)
30 |
--------------------------------------------------------------------------------
/canopen_proxy_driver/src/node_interfaces/node_canopen_proxy_driver.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Christoph Hellmann Santos
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 "canopen_proxy_driver/node_interfaces/node_canopen_proxy_driver.hpp"
16 | #include "canopen_proxy_driver/node_interfaces/node_canopen_proxy_driver_impl.hpp"
17 |
18 | using namespace ros2_canopen::node_interfaces;
19 |
20 | template class ros2_canopen::node_interfaces::NodeCanopenProxyDriver;
21 | template class ros2_canopen::node_interfaces::NodeCanopenProxyDriver<
22 | rclcpp_lifecycle::LifecycleNode>;
23 |
--------------------------------------------------------------------------------
/canopen_proxy_driver/src/proxy_driver.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Christoph Hellmann Santos
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 "canopen_proxy_driver/proxy_driver.hpp"
15 |
16 | using namespace ros2_canopen;
17 |
18 | ProxyDriver::ProxyDriver(rclcpp::NodeOptions node_options) : CanopenDriver(node_options)
19 | {
20 | node_canopen_proxy_driver_ =
21 | std::make_shared>(this);
22 | node_canopen_driver_ = std::static_pointer_cast(
23 | node_canopen_proxy_driver_);
24 | }
25 |
26 | #include "rclcpp_components/register_node_macro.hpp"
27 | RCLCPP_COMPONENTS_REGISTER_NODE(ros2_canopen::ProxyDriver)
28 |
--------------------------------------------------------------------------------
/canopen_proxy_driver/test/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | ament_add_gtest(test_node_interface
2 | test_node_interface.cpp
3 | )
4 | ament_target_dependencies(test_node_interface
5 | ${dependencies}
6 | )
7 | target_include_directories(test_node_interface PUBLIC
8 | ${CMAKE_CURRENT_SOURCE_DIR}/../include/
9 | )
10 | target_link_libraries(test_node_interface
11 | node_canopen_proxy_driver
12 | )
13 |
14 |
15 |
16 |
17 | ament_add_gtest(test_driver_component
18 | test_driver_component.cpp
19 | )
20 | ament_target_dependencies(test_driver_component
21 | ${dependencies}
22 | )
23 | target_include_directories(test_driver_component PUBLIC
24 | ${CMAKE_CURRENT_SOURCE_DIR}/../include/
25 | )
26 |
27 |
28 | file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/master.dcf DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
29 |
--------------------------------------------------------------------------------
/canopen_proxy_driver/test/test_driver_component.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Christoph Hellmann Santos
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 "canopen_base_driver/node_interfaces/node_canopen_base_driver.hpp"
21 | #include "gtest/gtest.h"
22 | using namespace rclcpp_components;
23 |
24 | TEST(ComponentLoad, test_load_component_1)
25 | {
26 | rclcpp::init(0, nullptr);
27 | auto exec = std::make_shared();
28 | auto manager = std::make_shared(exec);
29 |
30 | std::vector resources =
31 | manager->get_component_resources("canopen_proxy_driver");
32 |
33 | EXPECT_EQ(2u, resources.size());
34 |
35 | auto factory = manager->create_component_factory(resources[0]);
36 | auto instance_wrapper =
37 | factory->create_node_instance(rclcpp::NodeOptions().use_global_arguments(false));
38 |
39 | rclcpp::shutdown();
40 | }
41 |
42 | TEST(ComponentLoad, test_load_component_2)
43 | {
44 | rclcpp::init(0, nullptr);
45 | auto exec = std::make_shared();
46 | auto manager = std::make_shared(exec);
47 |
48 | std::vector resources =
49 | manager->get_component_resources("canopen_proxy_driver");
50 |
51 | EXPECT_EQ(2u, resources.size());
52 |
53 | auto factory = manager->create_component_factory(resources[1]);
54 | auto instance_wrapper =
55 | factory->create_node_instance(rclcpp::NodeOptions().use_global_arguments(false));
56 |
57 | rclcpp::shutdown();
58 | }
59 |
--------------------------------------------------------------------------------
/canopen_ros2_control/CHANGELOG.rst:
--------------------------------------------------------------------------------
1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 | Changelog for package canopen_ros2_control
3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4 |
5 | 0.2.9 (2024-04-16)
6 | ------------------
7 |
8 | 0.3.0 (2024-12-12)
9 | ------------------
10 | * pre-commit fix
11 | * impl operation mode
12 | * Add cyclic torque mode to cia402 driver and robot system controller (`#293 `_)
13 | * Add base functions for switching to cyclic torque mode
14 | * Add cyclic torque mode as effort interface to robot_system controller
15 | * Add documentation about cyclic torque mode.
16 | ---------
17 | Co-authored-by: Christoph Hellmann Santos
18 | * Fix clang format
19 | * Update canopen_system.hpp
20 | * Add pdo mapping support
21 | * Fix clang format
22 | * Fix pre-commit
23 | * Periodic messages sent, but not received properly.
24 | * Fix the bug that the rpdo queue keeps poping although it is empty.
25 | * Use proper function to get rpdo data
26 | * Fix bug in state interface indexing..
27 | * WIP: Extend the rpdo to have a queue (FIFO) to save the values.
28 | The read function take the latest value out of the queue and assign to the system interface.
29 | Need tests.
30 |
31 | 0.2.12 (2024-04-22)
32 | -------------------
33 | * 0.2.9
34 | * forthcoming
35 | * Contributors: ipa-vsp
36 |
37 | 0.2.8 (2024-01-19)
38 | ------------------
39 | * Update robot_system.cpp (`#168 `_)
40 | * Contributors: Christoph Hellmann Santos
41 |
42 | 0.2.7 (2023-06-30)
43 | ------------------
44 | * Correct Proxy controller after changes and update tests.
45 | * Contributors: Dr. Denis, Christoph Hellmann Santos
46 |
47 | 0.2.6 (2023-06-24)
48 | ------------------
49 |
50 | 0.2.5 (2023-06-23)
51 | ------------------
52 |
53 | 0.2.4 (2023-06-22)
54 | ------------------
55 |
56 | 0.2.3 (2023-06-22)
57 | ------------------
58 | * Solve buildfarm issues
59 | * Contributors: Christoph Hellmann Santos
60 |
61 | 0.2.2 (2023-06-21)
62 | ------------------
63 |
64 | 0.2.1 (2023-06-21)
65 | ------------------
66 | * Use consistenlty (uppercase) HEX output for NodeID and Index.
67 | * Contributors: Christoph Hellmann Santos, Denis Štogl
68 |
69 | 0.2.0 (2023-06-14)
70 | ------------------
71 | * Created package
72 | * Contributors: Błażej Sowa, Christoph Hellmann Santos, Denis Štogl, Lovro, Vishnuprasad Prachandabhanu, livanov93
73 |
--------------------------------------------------------------------------------
/canopen_ros2_control/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.8)
2 | project(canopen_ros2_control)
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 | set(THIS_PACKAGE_INCLUDE_DEPENDS
10 | canopen_402_driver
11 | canopen_core
12 | canopen_proxy_driver
13 | hardware_interface
14 | pluginlib
15 | rclcpp
16 | rclcpp_components
17 | rclcpp_lifecycle
18 | )
19 |
20 | find_package(ros2_control_test_assets)
21 | find_package(ament_cmake_gmock REQUIRED)
22 |
23 | find_package(ament_cmake REQUIRED)
24 | foreach(Dependency IN ITEMS ${THIS_PACKAGE_INCLUDE_DEPENDS})
25 | find_package(${Dependency} REQUIRED)
26 | endforeach()
27 |
28 | add_library(
29 | canopen_ros2_control
30 | SHARED
31 | src/canopen_system.cpp
32 | src/cia402_system.cpp
33 | src/robot_system.cpp
34 | )
35 |
36 |
37 |
38 | target_compile_features(canopen_ros2_control PUBLIC c_std_99 cxx_std_17) # Require C99 and C++17
39 | target_compile_options(canopen_ros2_control PUBLIC -fPIC -Wl,--no-undefined)
40 |
41 | target_include_directories(canopen_ros2_control PUBLIC include)
42 | ament_target_dependencies(canopen_ros2_control ${THIS_PACKAGE_INCLUDE_DEPENDS})
43 |
44 | # prevent pluginlib from using boost
45 | target_compile_definitions(canopen_ros2_control PUBLIC "PLUGINLIB__DISABLE_BOOST_FUNCTIONS")
46 |
47 | pluginlib_export_plugin_description_file(hardware_interface canopen_ros2_control.xml)
48 |
49 | install(
50 | TARGETS
51 | canopen_ros2_control
52 | RUNTIME DESTINATION bin
53 | ARCHIVE DESTINATION lib
54 | LIBRARY DESTINATION lib
55 | )
56 |
57 | install(
58 | DIRECTORY include/
59 | DESTINATION include
60 | )
61 |
62 | if(BUILD_TESTING)
63 | #find_package(ament_cmake_gmock REQUIRED)
64 | #find_package(ros2_control_test_assets REQUIRED)
65 |
66 | #ament_add_gmock(test_canopen_system test/test_canopen_system.cpp)
67 | #target_include_directories(test_canopen_system PRIVATE include)
68 | #ament_target_dependencies(
69 | #test_canopen_system ${THIS_PACKAGE_INCLUDE_DEPENDS} ros2_control_test_assets)
70 | endif()
71 |
72 | ament_export_include_directories(
73 | include
74 | )
75 | ament_export_libraries(
76 | canopen_ros2_control
77 | )
78 | ament_export_dependencies(
79 | ${THIS_PACKAGE_INCLUDE_DEPENDS}
80 | )
81 |
82 | ament_package()
83 |
--------------------------------------------------------------------------------
/canopen_ros2_control/canopen_ros2_control.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | ros2_control hardware interface.
7 |
8 |
9 |
12 |
13 | ros2_control hardware interface.
14 |
15 |
16 |
19 |
20 | ros2_control hardware interface.
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/canopen_ros2_control/include/canopen_ros2_control/helpers.hpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2023, Fraunhofer IPA
2 | // Copyright (c) 2022, StoglRobotics
3 | // Copyright (c) 2022, Stogl Robotics Consulting UG (haftungsbeschränkt) (template)
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | #ifndef CANOPEN_ROS2_CONTROL__HELPER_HPP_
18 | #define CANOPEN_ROS2_CONTROL__HELPER_HPP_
19 |
20 | #include
21 | #include
22 | #include
23 | #include
24 |
25 | namespace canopen_ros2_control
26 | {
27 | /**
28 | * @brief Struct for storing the data necessary for a triggering command.
29 | *
30 | * @details
31 | * A trigger command from a controller will write to the command double.
32 | * The result of the trigger operation will be written to the response double.
33 | * A result of 1.0 means the operation was successful.
34 | * A result of 0.0 means the operation failed.
35 | * Only a trigger command of 1.0 will be accepted and trigger the operation.
36 | * The command_available function can be used to check if a command is available,
37 | * undefined commands (other than 1.0) will be ignored.
38 | * The set_response function should be used to set the response value.
39 | * It will then clear the command.
40 | *
41 | */
42 | struct TriggerCommand
43 | {
44 | double command = std::numeric_limits::quiet_NaN();
45 | double response = std::numeric_limits::quiet_NaN();
46 | std::function trigger_function;
47 |
48 | bool try_trigger()
49 | {
50 | if (command == 1.0)
51 | {
52 | response = trigger_function() ? 1.0 : 0.0;
53 | command = std::numeric_limits::quiet_NaN();
54 | return true;
55 | }
56 | command = std::numeric_limits::quiet_NaN();
57 | return false;
58 | }
59 | };
60 |
61 | } // namespace canopen_ros2_control
62 | #endif
63 |
--------------------------------------------------------------------------------
/canopen_ros2_control/include/canopen_ros2_control/visibility_control.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022, Stogl Robotics Consulting UG (haftungsbeschränkt)
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 | #ifndef CANOPEN_ROS2_CONTROL__VISIBILITY_CONTROL_H_
16 | #define CANOPEN_ROS2_CONTROL__VISIBILITY_CONTROL_H_
17 |
18 | // This logic was borrowed (then namespaced) from the examples on the gcc wiki:
19 | // https://gcc.gnu.org/wiki/Visibility
20 |
21 | #if defined _WIN32 || defined __CYGWIN__
22 | #ifdef __GNUC__
23 | #define CANOPEN_ROS2_CONTROL__VISIBILITY_EXPORT __attribute__((dllexport))
24 | #define CANOPEN_ROS2_CONTROL__VISIBILITY_IMPORT __attribute__((dllimport))
25 | #else
26 | #define CANOPEN_ROS2_CONTROL__VISIBILITY_EXPORT __declspec(dllexport)
27 | #define CANOPEN_ROS2_CONTROL__VISIBILITY_IMPORT __declspec(dllimport)
28 | #endif
29 | #ifdef CANOPEN_ROS2_CONTROL__VISIBILITY_BUILDING_DLL
30 | #define CANOPEN_ROS2_CONTROL__VISIBILITY_PUBLIC CANOPEN_ROS2_CONTROL__VISIBILITY_EXPORT
31 | #else
32 | #define CANOPEN_ROS2_CONTROL__VISIBILITY_PUBLIC CANOPEN_ROS2_CONTROL__VISIBILITY_IMPORT
33 | #endif
34 | #define CANOPEN_ROS2_CONTROL__VISIBILITY_PUBLIC_TYPE CANOPEN_ROS2_CONTROL__VISIBILITY_PUBLIC
35 | #define CANOPEN_ROS2_CONTROL__VISIBILITY_LOCAL
36 | #else
37 | #define CANOPEN_ROS2_CONTROL__VISIBILITY_EXPORT __attribute__((visibility("default")))
38 | #define CANOPEN_ROS2_CONTROL__VISIBILITY_IMPORT
39 | #if __GNUC__ >= 4
40 | #define CANOPEN_ROS2_CONTROL__VISIBILITY_PUBLIC __attribute__((visibility("default")))
41 | #define CANOPEN_ROS2_CONTROL__VISIBILITY_LOCAL __attribute__((visibility("hidden")))
42 | #else
43 | #define CANOPEN_ROS2_CONTROL__VISIBILITY_PUBLIC
44 | #define CANOPEN_ROS2_CONTROL__VISIBILITY_LOCAL
45 | #endif
46 | #define CANOPEN_ROS2_CONTROL__VISIBILITY_PUBLIC_TYPE
47 | #endif
48 |
49 | #endif // CANOPEN_ROS2_CONTROL__VISIBILITY_CONTROL_H_
50 |
--------------------------------------------------------------------------------
/canopen_ros2_control/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | canopen_ros2_control
5 | 0.3.0
6 | ros2_control wrapper for ros2_canopen functionalities
7 | Lovro Ivanov
8 | Denis Stogl
9 |
10 | Apache-2.0
11 |
12 | ament_cmake
13 |
14 | canopen_402_driver
15 | canopen_core
16 | canopen_proxy_driver
17 | hardware_interface
18 | pluginlib
19 | rclcpp
20 | rclcpp_components
21 | rclcpp_lifecycle
22 |
23 | ament_cmake_gmock
24 | ros2_control_test_assets
25 |
26 |
27 | ament_cmake
28 |
29 |
30 |
--------------------------------------------------------------------------------
/canopen_ros2_controllers/CHANGELOG.rst:
--------------------------------------------------------------------------------
1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 | Changelog for package canopen_ros2_controllers
3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4 |
5 | 0.2.9 (2024-04-16)
6 | ------------------
7 |
8 | 0.3.0 (2024-12-12)
9 | ------------------
10 |
11 | 0.2.12 (2024-04-22)
12 | -------------------
13 | * 0.2.9
14 | * forthcoming
15 | * Contributors: ipa-vsp
16 |
17 | 0.2.8 (2024-01-19)
18 | ------------------
19 | * Remove controller tests (`#249 `_)
20 | * Disable controller tests for now (`#231 `_)
21 | * Disable controller tests for now
22 | * Update iron.yml
23 | * Fix ci
24 | * Contributors: Christoph Hellmann Santos, Vishnuprasad Prachandabhanu
25 |
26 | 0.2.7 (2023-06-30)
27 | ------------------
28 | * Correct Proxy controller after changes and update tests.
29 | * Contributors: Dr. Denis, Christoph Hellmann Santos
30 |
31 | 0.2.6 (2023-06-24)
32 | ------------------
33 |
34 | 0.2.5 (2023-06-23)
35 | ------------------
36 |
37 | 0.2.4 (2023-06-22)
38 | ------------------
39 |
40 | 0.2.3 (2023-06-22)
41 | ------------------
42 |
43 | 0.2.2 (2023-06-21)
44 | ------------------
45 |
46 | 0.2.1 (2023-06-21)
47 | ------------------
48 | * Fix QoS build warning canopen_ros2_controllers
49 | * Don't use ros2_control_test_assets since not needed anymore. Add load tests for all controllers.
50 | * Contributors: Christoph Hellmann Santos, Denis Štogl, Vishnuprasad Prachandabhanu
51 |
52 | 0.2.0 (2023-06-14)
53 | ------------------
54 | * Created package
55 | * Contributors: Błażej Sowa, Christoph Hellmann Santos, Denis Štogl, Dr.-Ing. Denis Štogl, Lovro, livanov93
56 |
--------------------------------------------------------------------------------
/canopen_ros2_controllers/canopen_ros2_controllers.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 | Generic controller for Canopen devices providing service interfaces through ros2_control stack to the can devices.
6 |
7 |
8 |
10 |
11 | Generic controller for Canopen 402 devices providing service interfaces through ros2_control stack to the can devices.
12 |
13 |
14 |
16 |
17 | Generic controller for Canopen 402 devices providing service interfaces through ros2_control stack to the can devices.
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/canopen_ros2_controllers/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | canopen_ros2_controllers
5 | 0.3.0
6 | ros2_control controllers for ros2_canopen functionalities
7 | Denis Stogl
8 | Lovro Ivanov
9 |
10 | Apache-2.0
11 |
12 | ament_cmake
13 |
14 | canopen_402_driver
15 | canopen_interfaces
16 | canopen_proxy_driver
17 | controller_interface
18 | controller_manager
19 | hardware_interface
20 | pluginlib
21 | rclcpp
22 | rclcpp_lifecycle
23 | realtime_tools
24 | std_msgs
25 | std_srvs
26 |
27 | ament_cmake_gmock
28 |
29 |
30 | ament_cmake
31 |
32 |
33 |
--------------------------------------------------------------------------------
/canopen_ros2_controllers/test/test_load_canopen_proxy_controller.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022, Stogl Robotics Consulting UG (haftungsbeschränkt)
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 "controller_manager/controller_manager.hpp"
19 | #include "hardware_interface/resource_manager.hpp"
20 | #include "rclcpp/executor.hpp"
21 | #include "rclcpp/executors/single_threaded_executor.hpp"
22 | #include "rclcpp/utilities.hpp"
23 |
24 | TEST(TestLoadCanopenProxyController, load_controller)
25 | {
26 | rclcpp::init(0, nullptr);
27 |
28 | std::shared_ptr executor =
29 | std::make_shared();
30 |
31 | controller_manager::ControllerManager cm(
32 | std::make_unique(), executor, "test_controller_manager");
33 |
34 | ASSERT_NO_THROW(cm.load_controller(
35 | "test_canopen_ros2_controllers", "canopen_ros2_controllers/CanopenProxyController"));
36 |
37 | rclcpp::shutdown();
38 | }
39 |
--------------------------------------------------------------------------------
/canopen_ros2_controllers/test/test_load_cia402_device_controller.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt)
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 "controller_manager/controller_manager.hpp"
19 | #include "hardware_interface/resource_manager.hpp"
20 | #include "rclcpp/executor.hpp"
21 | #include "rclcpp/executors/single_threaded_executor.hpp"
22 | #include "rclcpp/utilities.hpp"
23 |
24 | TEST(TestLoadCanopenProxyController, load_controller)
25 | {
26 | rclcpp::init(0, nullptr);
27 |
28 | std::shared_ptr executor =
29 | std::make_shared();
30 |
31 | controller_manager::ControllerManager cm(
32 | std::make_unique(), executor, "test_controller_manager");
33 |
34 | ASSERT_NO_THROW(cm.load_controller(
35 | "test_canopen_ros2_controllers", "canopen_ros2_controllers/Cia402DeviceController"));
36 |
37 | rclcpp::shutdown();
38 | }
39 |
--------------------------------------------------------------------------------
/canopen_ros2_controllers/test/test_load_cia402_robot_controller.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt)
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 "controller_manager/controller_manager.hpp"
19 | #include "hardware_interface/resource_manager.hpp"
20 | #include "rclcpp/executor.hpp"
21 | #include "rclcpp/executors/single_threaded_executor.hpp"
22 | #include "rclcpp/utilities.hpp"
23 |
24 | TEST(TestLoadCanopenProxyController, load_controller)
25 | {
26 | rclcpp::init(0, nullptr);
27 |
28 | std::shared_ptr executor =
29 | std::make_shared();
30 |
31 | controller_manager::ControllerManager cm(
32 | std::make_unique(), executor, "test_controller_manager");
33 |
34 | ASSERT_NO_THROW(cm.load_controller(
35 | "test_canopen_ros2_controllers", "canopen_ros2_controllers/Cia402RobotController"));
36 |
37 | rclcpp::shutdown();
38 | }
39 |
--------------------------------------------------------------------------------
/canopen_tests/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.8)
2 | project(canopen_tests)
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(lely_core_libraries REQUIRED)
11 |
12 |
13 | generate_dcf(simple)
14 | generate_dcf(canopen_system)
15 | cogen_dcf(cia402_system)
16 | cogen_dcf(cia402_namespaced_system)
17 | cogen_dcf(cia402)
18 | generate_dcf(cia402_lifecycle)
19 | cogen_dcf(cia402_diagnostics)
20 | generate_dcf(simple_lifecycle)
21 | cogen_dcf(simple_diagnostics)
22 | generate_dcf(robot_control)
23 |
24 | install(DIRECTORY
25 | launch rviz urdf launch_tests
26 | DESTINATION share/${PROJECT_NAME}
27 | )
28 |
29 |
30 |
31 | if(BUILD_TESTING)
32 | if(CANOPEN_ENABLED)
33 | find_package(launch_testing_ament_cmake REQUIRED)
34 | add_launch_test(launch_tests/test_proxy_driver.py)
35 | add_launch_test(launch_tests/test_proxy_lifecycle_driver.py)
36 | endif()
37 | endif()
38 |
39 | ament_package()
40 |
--------------------------------------------------------------------------------
/canopen_tests/README.md:
--------------------------------------------------------------------------------
1 | # CANopen Tests
2 |
3 | Enable launch tests with --cmake-args -DCANOPEN_ENABLED.
4 | They can only be run on devices that have vcan0 enabled.
5 |
--------------------------------------------------------------------------------
/canopen_tests/ROS_NAMESPACES.md:
--------------------------------------------------------------------------------
1 | The `cia402_namespaced_system.launch.py` example demonstrates how to run a
2 | CIA402 system in a namespace to allow multiple CANOpen-based robots in the
3 | same ROS domain. This example is necessary because the controller names
4 | are picked up from `ros2_controllers.yaml` and we must define their names
5 | in that file with a `__namespace__/controller_name:` key, then use
6 | ReplaceString from `nav2_common` to dynamically add the namespace to the
7 | controller definition.
8 |
9 | For a proxy system, no example is included; it's sufficient to include, e.g.
10 | the `proxy_setup.launch.py` launch description in another launch file and
11 | push a namespace onto it with PushROSNamespace in the ordinary way.
12 |
--------------------------------------------------------------------------------
/canopen_tests/config/canopen_system/bus.yml:
--------------------------------------------------------------------------------
1 | options:
2 | dcf_path: "@BUS_CONFIG_PATH@"
3 |
4 | master:
5 | node_id: 1
6 | driver: "ros2_canopen::MasterDriver"
7 | package: "canopen_master_driver"
8 |
9 | proxy_device_1:
10 | node_id: 2
11 | dcf: "simple.eds"
12 | driver: "ros2_canopen::ProxyDriver"
13 | package: "canopen_proxy_driver"
14 |
15 | proxy_device_2:
16 | node_id: 3
17 | dcf: "simple.eds"
18 | driver: "ros2_canopen::ProxyDriver"
19 | package: "canopen_proxy_driver"
20 |
--------------------------------------------------------------------------------
/canopen_tests/config/canopen_system/ros2_controllers.yaml:
--------------------------------------------------------------------------------
1 | controller_manager:
2 | ros__parameters:
3 | update_rate: 10 # Hz
4 |
5 | joint_state_broadcaster:
6 | type: joint_state_broadcaster/JointStateBroadcaster
7 |
8 | node_1_controller:
9 | type: canopen_ros2_controllers/CanopenProxyController
10 |
11 | node_1_controller:
12 | ros__parameters:
13 | joint: node_1
14 |
--------------------------------------------------------------------------------
/canopen_tests/config/cia402/bus.yml:
--------------------------------------------------------------------------------
1 | options:
2 | dcf_path: "@BUS_CONFIG_PATH@"
3 |
4 | master:
5 | node_id: 1
6 | driver: "ros2_canopen::MasterDriver"
7 | package: "canopen_master_driver"
8 | sync_period: 10000
9 |
10 | defaults:
11 | dcf: "cia402_slave.eds"
12 | driver: "ros2_canopen::Cia402Driver"
13 | package: "canopen_402_driver"
14 | period: 10
15 | revision_number: 0
16 | sdo:
17 | - {index: 0x60C2, sub_index: 1, value: 50} # Set interpolation time for cyclic modes to 50 ms
18 | - {index: 0x60C2, sub_index: 2, value: -3} # Set base 10-3s
19 | - {index: 0x6081, sub_index: 0, value: 1000}
20 | - {index: 0x6083, sub_index: 0, value: 2000}
21 | tpdo: # TPDO needed statusword, actual velocity, actual position, mode of operation
22 | 1:
23 | enabled: true
24 | cob_id: "auto"
25 | transmission: 0x01
26 | mapping:
27 | - {index: 0x6041, sub_index: 0} # status word
28 | - {index: 0x6061, sub_index: 0} # mode of operation display
29 | 2:
30 | enabled: true
31 | cob_id: "auto"
32 | transmission: 0x01
33 | mapping:
34 | - {index: 0x6064, sub_index: 0} # position actual value
35 | - {index: 0x606c, sub_index: 0} # velocity actual position
36 | 3:
37 | enabled: false
38 | 4:
39 | enabled: false
40 | rpdo: # RPDO needed controlword, target position, target velocity, mode of operation
41 | 1:
42 | enabled: true
43 | cob_id: "auto"
44 | mapping:
45 | - {index: 0x6040, sub_index: 0} # controlword
46 | - {index: 0x6060, sub_index: 0} # mode of operation
47 | 2:
48 | enabled: true
49 | cob_id: "auto"
50 | mapping:
51 | - {index: 0x607A, sub_index: 0} # target position
52 | - {index: 0x60FF, sub_index: 0} # target velocity
53 |
54 | nodes:
55 | cia402_device_1:
56 | node_id: 2
57 | namespace: "/test1"
58 | cia402_device_2:
59 | node_id: 3
60 | cia402_device_3:
61 | node_id: 4
62 | cia402_device_4:
63 | node_id: 5
64 | cia402_device_5:
65 | node_id: 6
66 | cia402_device_6:
67 | node_id: 7
68 |
--------------------------------------------------------------------------------
/canopen_tests/config/cia402_diagnostics/bus.yml:
--------------------------------------------------------------------------------
1 | options:
2 | dcf_path: "@BUS_CONFIG_PATH@"
3 |
4 | master:
5 | node_id: 1
6 | driver: "ros2_canopen::MasterDriver"
7 | package: "canopen_master_driver"
8 | sync_period: 10000
9 |
10 | defaults:
11 | dcf: "cia402_slave.eds"
12 | driver: "ros2_canopen::Cia402Driver"
13 | package: "canopen_402_driver"
14 | diagnostics:
15 | enable: true
16 | period: 1000 # in milliseconds
17 | revision_number: 0
18 | sdo:
19 | - {index: 0x60C2, sub_index: 1, value: 50} # Set interpolation time for cyclic modes to 50 ms
20 | - {index: 0x60C2, sub_index: 2, value: -3} # Set base 10-3s
21 | - {index: 0x6081, sub_index: 0, value: 1000}
22 | - {index: 0x6083, sub_index: 0, value: 2000}
23 | tpdo: # TPDO needed statusword, actual velocity, actual position, mode of operation
24 | 1:
25 | enabled: true
26 | cob_id: "auto"
27 | transmission: 0x01
28 | mapping:
29 | - {index: 0x6041, sub_index: 0} # status word
30 | - {index: 0x6061, sub_index: 0} # mode of operation display
31 | 2:
32 | enabled: true
33 | cob_id: "auto"
34 | transmission: 0x01
35 | mapping:
36 | - {index: 0x6064, sub_index: 0} # position actual value
37 | - {index: 0x606c, sub_index: 0} # velocity actual position
38 | 3:
39 | enabled: false
40 | 4:
41 | enabled: false
42 | rpdo: # RPDO needed controlword, target position, target velocity, mode of operation
43 | 1:
44 | enabled: true
45 | cob_id: "auto"
46 | mapping:
47 | - {index: 0x6040, sub_index: 0} # controlword
48 | - {index: 0x6060, sub_index: 0} # mode of operation
49 | 2:
50 | enabled: true
51 | cob_id: "auto"
52 | mapping:
53 | - {index: 0x607A, sub_index: 0} # target position
54 | - {index: 0x60FF, sub_index: 0} # target velocity
55 |
56 | nodes:
57 | cia402_device_1:
58 | node_id: 2
59 | cia402_device_2:
60 | node_id: 3
61 | cia402_device_3:
62 | node_id: 4
63 |
--------------------------------------------------------------------------------
/canopen_tests/config/cia402_lifecycle/bus.yml:
--------------------------------------------------------------------------------
1 | options:
2 | dcf_path: "@BUS_CONFIG_PATH@"
3 |
4 | master:
5 | node_id: 1
6 | driver: "ros2_canopen::LifecycleMasterDriver"
7 | package: "canopen_master_driver"
8 | sync_period: 20000
9 |
10 | cia402_device_1:
11 | node_id: 2
12 | dcf: "cia402_slave.eds"
13 | driver: "ros2_canopen::LifecycleCia402Driver"
14 | package: "canopen_402_driver"
15 | period: 20
16 | enable_lazy_load: false
17 | revision_number: 0
18 | sdo:
19 | - {index: 0x60C2, sub_index: 1, value: 50} # Set interpolation time for cyclic modes to 50 ms
20 | - {index: 0x60C2, sub_index: 2, value: -3} # Set base 10-3s
21 | tpdo: # TPDO needed statusword, actual velocity, actual position, mode of operation
22 | 1:
23 | enabled: true
24 | cob_id: "auto"
25 | transmission: 0x01
26 | mapping:
27 | - {index: 0x6041, sub_index: 0} # status word
28 | - {index: 0x6061, sub_index: 0} # mode of operation display
29 | 2:
30 | enabled: true
31 | cob_id: "auto"
32 | transmission: 0x01
33 | mapping:
34 | - {index: 0x6064, sub_index: 0} # position actual value
35 | - {index: 0x606c, sub_index: 0} # velocity actual position
36 | 3:
37 | enabled: false
38 | 4:
39 | enabled: false
40 | rpdo: # RPDO needed controlword, target position, target velocity, mode of operation
41 | 1:
42 | enabled: true
43 | cob_id: "auto"
44 | mapping:
45 | - {index: 0x6040, sub_index: 0} # controlword
46 | - {index: 0x6060, sub_index: 0} # mode of operation
47 | 2:
48 | enabled: true
49 | cob_id: "auto"
50 | mapping:
51 | - {index: 0x607A, sub_index: 0} # target position
52 | - {index: 0x60FF, sub_index: 0} # target velocity
53 |
--------------------------------------------------------------------------------
/canopen_tests/config/cia402_namespaced_system/bus.yml:
--------------------------------------------------------------------------------
1 | options:
2 | dcf_path: "@BUS_CONFIG_PATH@"
3 |
4 | master:
5 | node_id: 1
6 | driver: "ros2_canopen::MasterDriver"
7 | package: "canopen_master_driver"
8 | sync_period: 10000
9 |
10 | defaults:
11 | dcf: "cia402_slave.eds"
12 | driver: "ros2_canopen::Cia402Driver"
13 | package: "canopen_402_driver"
14 | period: 10
15 | revision_number: 0
16 | sdo:
17 | - {index: 0x60C2, sub_index: 1, value: 50} # Set interpolation time for cyclic modes to 50 ms
18 | - {index: 0x60C2, sub_index: 2, value: -3} # Set base 10-3s
19 | - {index: 0x6081, sub_index: 0, value: 1000}
20 | - {index: 0x6083, sub_index: 0, value: 2000}
21 | tpdo: # TPDO needed statusword, actual velocity, actual position, mode of operation
22 | 1:
23 | enabled: true
24 | cob_id: "auto"
25 | transmission: 0x01
26 | mapping:
27 | - {index: 0x6041, sub_index: 0} # status word
28 | - {index: 0x6061, sub_index: 0} # mode of operation display
29 | 2:
30 | enabled: true
31 | cob_id: "auto"
32 | transmission: 0x01
33 | mapping:
34 | - {index: 0x6064, sub_index: 0} # position actual value
35 | - {index: 0x606c, sub_index: 0} # velocity actual position
36 | 3:
37 | enabled: false
38 | 4:
39 | enabled: false
40 | rpdo: # RPDO needed controlword, target position, target velocity, mode of operation
41 | 1:
42 | enabled: true
43 | cob_id: "auto"
44 | mapping:
45 | - {index: 0x6040, sub_index: 0} # controlword
46 | - {index: 0x6060, sub_index: 0} # mode of operation
47 | 2:
48 | enabled: true
49 | cob_id: "auto"
50 | mapping:
51 | - {index: 0x607A, sub_index: 0} # target position
52 | - {index: 0x60FF, sub_index: 0} # target velocity
53 |
54 | nodes:
55 | cia402_device_1:
56 | node_id: 2
57 |
--------------------------------------------------------------------------------
/canopen_tests/config/cia402_namespaced_system/ros2_controllers.yaml:
--------------------------------------------------------------------------------
1 | __namespace__/controller_manager:
2 | ros__parameters:
3 | update_rate: 10 # Hz
4 |
5 | joint_state_broadcaster:
6 | type: joint_state_broadcaster/JointStateBroadcaster
7 |
8 | cia402_device_1_controller:
9 | type: canopen_ros2_controllers/Cia402DeviceController
10 |
11 | joint_trajectory_controller:
12 | type: joint_trajectory_controller/JointTrajectoryController
13 |
14 | forward_position_controller:
15 | type: forward_command_controller/ForwardCommandController
16 |
17 | __namespace__/cia402_device_1_controller:
18 | ros__parameters:
19 | joint: node_1
20 |
21 | __namespace__/forward_position_controller:
22 | ros__parameters:
23 | joints:
24 | - node_1
25 | interface_name: position
26 |
27 | __namespace__/joint_trajectory_controller:
28 | ros__parameters:
29 | joints:
30 | - node_1
31 | command_interfaces:
32 | - position
33 | state_interfaces:
34 | - position
35 | - velocity
36 | state_publish_rate: 100.0
37 | action_monitor_rate: 20.0
38 | allow_partial_joints_goal: false
39 | constraints:
40 | stopped_velocity_tolerance: 0.2
41 | goal_time: 0.0
42 | node_1: { trajectory: 0.2, goal: 0.1 }
43 |
--------------------------------------------------------------------------------
/canopen_tests/config/cia402_system/bus.yml:
--------------------------------------------------------------------------------
1 | options:
2 | dcf_path: "@BUS_CONFIG_PATH@"
3 |
4 | master:
5 | node_id: 1
6 | driver: "ros2_canopen::MasterDriver"
7 | package: "canopen_master_driver"
8 | sync_period: 10000
9 |
10 | defaults:
11 | dcf: "cia402_slave.eds"
12 | driver: "ros2_canopen::Cia402Driver"
13 | package: "canopen_402_driver"
14 | period: 10
15 | revision_number: 0
16 | sdo:
17 | - {index: 0x60C2, sub_index: 1, value: 50} # Set interpolation time for cyclic modes to 50 ms
18 | - {index: 0x60C2, sub_index: 2, value: -3} # Set base 10-3s
19 | - {index: 0x6081, sub_index: 0, value: 1000}
20 | - {index: 0x6083, sub_index: 0, value: 2000}
21 | tpdo: # TPDO needed statusword, actual velocity, actual position, mode of operation
22 | 1:
23 | enabled: true
24 | cob_id: "auto"
25 | transmission: 0x01
26 | mapping:
27 | - {index: 0x6041, sub_index: 0} # status word
28 | - {index: 0x6061, sub_index: 0} # mode of operation display
29 | 2:
30 | enabled: true
31 | cob_id: "auto"
32 | transmission: 0x01
33 | mapping:
34 | - {index: 0x6064, sub_index: 0} # position actual value
35 | - {index: 0x606c, sub_index: 0} # velocity actual position
36 | 3:
37 | enabled: false
38 | 4:
39 | enabled: false
40 | rpdo: # RPDO needed controlword, target position, target velocity, mode of operation
41 | 1:
42 | enabled: true
43 | cob_id: "auto"
44 | mapping:
45 | - {index: 0x6040, sub_index: 0} # controlword
46 | - {index: 0x6060, sub_index: 0} # mode of operation
47 | 2:
48 | enabled: true
49 | cob_id: "auto"
50 | mapping:
51 | - {index: 0x607A, sub_index: 0} # target position
52 | - {index: 0x60FF, sub_index: 0} # target velocity
53 |
54 | nodes:
55 | cia402_device_1:
56 | node_id: 2
57 |
--------------------------------------------------------------------------------
/canopen_tests/config/cia402_system/ros2_controllers.yaml:
--------------------------------------------------------------------------------
1 | controller_manager:
2 | ros__parameters:
3 | update_rate: 10 # Hz
4 |
5 | joint_state_broadcaster:
6 | type: joint_state_broadcaster/JointStateBroadcaster
7 |
8 | cia402_device_1_controller:
9 | type: canopen_ros2_controllers/Cia402DeviceController
10 |
11 | joint_trajectory_controller:
12 | type: joint_trajectory_controller/JointTrajectoryController
13 |
14 | forward_position_controller:
15 | type: forward_command_controller/ForwardCommandController
16 |
17 | cia402_device_1_controller:
18 | ros__parameters:
19 | joint: node_1
20 |
21 | forward_position_controller:
22 | ros__parameters:
23 | joints:
24 | - node_1
25 | interface_name: position
26 |
27 | joint_trajectory_controller:
28 | ros__parameters:
29 | joints:
30 | - node_1
31 | command_interfaces:
32 | - position
33 | state_interfaces:
34 | - position
35 | - velocity
36 | state_publish_rate: 100.0
37 | action_monitor_rate: 20.0
38 | allow_partial_joints_goal: false
39 | constraints:
40 | stopped_velocity_tolerance: 0.2
41 | goal_time: 0.0
42 | node_1: { trajectory: 0.2, goal: 0.1 }
43 |
--------------------------------------------------------------------------------
/canopen_tests/config/robot_control/ros2_controllers.yaml:
--------------------------------------------------------------------------------
1 | controller_manager:
2 | ros__parameters:
3 | update_rate: 100 # Hz
4 | joint_state_broadcaster:
5 | type: joint_state_broadcaster/JointStateBroadcaster
6 |
7 | robot_controller:
8 | type: canopen_ros2_controllers/Cia402RobotController
9 |
10 | forward_position_controller:
11 | type: forward_command_controller/ForwardCommandController
12 |
13 | robot_controller:
14 | ros__parameters:
15 | joints:
16 | - joint1
17 | - joint2
18 | operation_mode: 1
19 | command_poll_freq: 5
20 |
21 | forward_position_controller:
22 | ros__parameters:
23 | joints:
24 | - joint1
25 | - joint2
26 | interface_name: position
27 |
28 | # joint_trajectory_controller:
29 | # ros__parameters:
30 | # joints:
31 | # - prbt_joint_1
32 | # - prbt_joint_2
33 | # - prbt_joint_3
34 | # - prbt_joint_4
35 | # - prbt_joint_5
36 | # - prbt_joint_6
37 | # command_interfaces:
38 | # - position
39 | # state_interfaces:
40 | # - position
41 | # - velocity
42 | # state_publish_rate: 100.0
43 | # action_monitor_rate: 20.0
44 | # allow_partial_joints_goal: false
45 | # constraints:
46 | # stopped_velocity_tolerance: 0.2
47 | # goal_time: 0.6
48 | # stopped_velocity_tolerance: 0.05
49 | # prbt_joint_1: {trajectory: 0.157, goal: 0.01}
50 | # prbt_joint_2: {trajectory: 0.157, goal: 0.01}
51 | # prbt_joint_3: {trajectory: 0.157, goal: 0.01}
52 | # prbt_joint_4: {trajectory: 0.157, goal: 0.01}
53 | # prbt_joint_5: {trajectory: 0.157, goal: 0.01}
54 | # prbt_joint_6: {trajectory: 0.157, goal: 0.01}
55 |
--------------------------------------------------------------------------------
/canopen_tests/config/simple/bus.yml:
--------------------------------------------------------------------------------
1 | options:
2 | dcf_path: "@BUS_CONFIG_PATH@"
3 |
4 | master:
5 | node_id: 1
6 | driver: "ros2_canopen::MasterDriver"
7 | package: "canopen_master_driver"
8 |
9 | proxy_device_1:
10 | node_id: 2
11 | dcf: "simple.eds"
12 | driver: "ros2_canopen::ProxyDriver"
13 | package: "canopen_proxy_driver"
14 | polling: true
15 | period: 10
16 | namespace: "/test1"
17 |
18 | proxy_device_2:
19 | node_id: 3
20 | dcf: "simple.eds"
21 | driver: "ros2_canopen::ProxyDriver"
22 | package: "canopen_proxy_driver"
23 | polling: true
24 | period: 10
25 | namespace: "/test2"
26 |
--------------------------------------------------------------------------------
/canopen_tests/config/simple_diagnostics/bus.yml:
--------------------------------------------------------------------------------
1 | options:
2 | dcf_path: "@BUS_CONFIG_PATH@"
3 |
4 | master:
5 | node_id: 1
6 | driver: "ros2_canopen::MasterDriver"
7 | package: "canopen_master_driver"
8 |
9 | defaults:
10 | dcf: "simple.eds"
11 | driver: "ros2_canopen::ProxyDriver"
12 | package: "canopen_proxy_driver"
13 | polling: true
14 | period: 10
15 | diagnostics:
16 | enable: true
17 | period: 1000 # in milliseconds
18 |
19 | nodes:
20 | proxy_device_1:
21 | node_id: 2
22 | proxy_device_2:
23 | node_id: 3
24 |
--------------------------------------------------------------------------------
/canopen_tests/config/simple_lifecycle/bus.yml:
--------------------------------------------------------------------------------
1 | options:
2 | dcf_path: "@BUS_CONFIG_PATH@"
3 |
4 | master:
5 | node_id: 1
6 | driver: "ros2_canopen::LifecycleMasterDriver"
7 | package: "canopen_master_driver"
8 |
9 | proxy_device_1:
10 | node_id: 2
11 | dcf: "simple.eds"
12 | driver: "ros2_canopen::LifecycleProxyDriver"
13 | package: "canopen_proxy_driver"
14 |
15 | proxy_device_2:
16 | node_id: 3
17 | dcf: "simple.eds"
18 | driver: "ros2_canopen::LifecycleProxyDriver"
19 | package: "canopen_proxy_driver"
20 |
--------------------------------------------------------------------------------
/canopen_tests/launch/analyzers/cia402_diagnostic_analyzer.yaml:
--------------------------------------------------------------------------------
1 | analyzers:
2 | ros__parameters:
3 | path: Aggregation
4 | cia402_device_1:
5 | type: diagnostic_aggregator/GenericAnalyzer
6 | path: Cia402Device1
7 | contains: [ 'cia402_device_1' ]
8 | cia402_device_2:
9 | type: diagnostic_aggregator/GenericAnalyzer
10 | path: Cia402Device2
11 | contains: [ 'cia402_device_2' ]
12 | cia402_device_3:
13 | type: diagnostic_aggregator/GenericAnalyzer
14 | path: Cia402Device3
15 | contains: [ 'cia402_device_3' ]
16 |
--------------------------------------------------------------------------------
/canopen_tests/launch/analyzers/proxy_diagnostic_analyzer.yaml:
--------------------------------------------------------------------------------
1 | analyzers:
2 | ros__parameters:
3 | path: Aggregation
4 | proxy_device_1:
5 | type: diagnostic_aggregator/GenericAnalyzer
6 | path: ProxyDevice1
7 | contains: [ 'proxy_device_1' ]
8 | proxy_device_2:
9 | type: diagnostic_aggregator/GenericAnalyzer
10 | path: ProxyDevice2
11 | contains: [ 'proxy_device_2' ]
12 |
--------------------------------------------------------------------------------
/canopen_tests/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | canopen_tests
5 | 0.3.0
6 | Package with tests for ros2_canopen
7 | Christoph Hellmann Santos
8 | Apache-2.0
9 |
10 | ament_cmake
11 |
12 | lely_core_libraries
13 |
14 | canopen_402_driver
15 | canopen_core
16 | canopen_proxy_driver
17 |
18 | xacro
19 | controller_manager
20 | robot_state_publisher
21 |
22 | joint_state_broadcaster
23 | joint_trajectory_controller
24 | forward_command_controller
25 |
26 | canopen_fake_slaves
27 | canopen_ros2_controllers
28 |
29 | ament_lint_auto
30 |
31 |
32 | ament_cmake
33 |
34 |
35 |
--------------------------------------------------------------------------------
/canopen_tests/urdf/canopen_system/canopen_system.ros2_control.xacro:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
13 |
14 | canopen_ros2_control/CanopenSystem
15 | ${bus_config}
16 | ${master_config}
17 | ${can_interface_name}
18 | "${master_bin}"
19 |
20 |
21 | 2
22 |
23 |
24 | 3
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/canopen_tests/urdf/canopen_system/canopen_system.urdf.xacro:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/canopen_tests/urdf/cia402_system/cia402_system.ros2_control.xacro:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
13 |
14 | canopen_ros2_control/Cia402System
15 | ${bus_config}
16 | ${master_config}
17 | ${can_interface_name}
18 | "${master_bin}"
19 |
20 |
21 | 2
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/canopen_tests/urdf/cia402_system/cia402_system.urdf.xacro:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/canopen_tests/urdf/robot_controller/robot_controller.macro.xacro:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/canopen_tests/urdf/robot_controller/robot_controller.ros2_control.xacro:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
12 |
13 | canopen_ros2_control/RobotSystem
14 | ${bus_config}
15 | ${master_config}
16 | ${can_interface_name}
17 | "${master_bin}"
18 |
19 |
20 | joint_1
21 |
22 |
23 |
24 | joint_2
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/canopen_tests/urdf/robot_controller/robot_controller.urdf.xacro:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
13 |
14 |
15 |
16 |
23 |
24 |
--------------------------------------------------------------------------------
/canopen_utils/CHANGELOG.rst:
--------------------------------------------------------------------------------
1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 | Changelog for package canopen_utils
3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4 |
5 | 0.2.9 (2024-04-16)
6 | ------------------
7 |
8 | 0.3.0 (2024-12-12)
9 | ------------------
10 |
11 | 0.2.12 (2024-04-22)
12 | -------------------
13 | * 0.2.9
14 | * forthcoming
15 | * Contributors: ipa-vsp
16 |
17 | 0.2.8 (2024-01-19)
18 | ------------------
19 |
20 | 0.2.7 (2023-06-30)
21 | ------------------
22 | * Add missing license headers and activate ament_copyright
23 | * Fix maintainer naming
24 | * Contributors: Christoph Hellmann Santos
25 |
26 | 0.2.6 (2023-06-24)
27 | ------------------
28 |
29 | 0.2.5 (2023-06-23)
30 | ------------------
31 |
32 | 0.2.4 (2023-06-22)
33 | ------------------
34 |
35 | 0.2.3 (2023-06-22)
36 | ------------------
37 |
38 | 0.2.2 (2023-06-21)
39 | ------------------
40 |
41 | 0.2.1 (2023-06-21)
42 | ------------------
43 | * Add more tidy launch_test_node.py
44 | * Contributors: Christoph Hellmann Santos
45 |
46 | 0.2.0 (2023-06-14)
47 | ------------------
48 | * Created package
49 | * Contributors: Błażej Sowa, Christoph Hellmann Santos, Vishnuprasad Prachandabhanu
50 |
--------------------------------------------------------------------------------
/canopen_utils/canopen_utils/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ros-industrial/ros2_canopen/f144f280f8e3c3f47491ae15e7f44ece1781db1a/canopen_utils/canopen_utils/__init__.py
--------------------------------------------------------------------------------
/canopen_utils/no_tests/_test_copyright.py:
--------------------------------------------------------------------------------
1 | # Copyright 2015 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 | from ament_copyright.main import main
16 | import pytest
17 |
18 |
19 | @pytest.mark.copyright
20 | @pytest.mark.linter
21 | def test_copyright():
22 | rc = main(argv=[".", "test"])
23 | assert rc == 0, "Found errors"
24 |
--------------------------------------------------------------------------------
/canopen_utils/no_tests/_test_flake8.py:
--------------------------------------------------------------------------------
1 | # Copyright 2017 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 | from ament_flake8.main import main_with_errors
16 | import pytest
17 |
18 |
19 | @pytest.mark.flake8
20 | @pytest.mark.linter
21 | def test_flake8():
22 | rc, errors = main_with_errors(argv=[])
23 | assert rc == 0, "Found %d code style errors / warnings:\n" % len(errors) + "\n".join(errors)
24 |
--------------------------------------------------------------------------------
/canopen_utils/no_tests/_test_pep257.py:
--------------------------------------------------------------------------------
1 | # Copyright 2015 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 | from ament_pep257.main import main
16 | import pytest
17 |
18 |
19 | @pytest.mark.linter
20 | @pytest.mark.pep257
21 | def test_pep257():
22 | rc = main(argv=[".", "test"])
23 | assert rc == 0, "Found code style errors / warnings"
24 |
--------------------------------------------------------------------------------
/canopen_utils/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | canopen_utils
5 | 0.3.0
6 | Utils for working with ros2_canopen.
7 | Christoph Hellmann Santos
8 | Apache-2.0
9 | rclpy
10 | canopen_interfaces
11 | lifecycle_msgs
12 | std_msgs
13 | ament_lint_auto
14 |
15 | ament_python
16 |
17 |
18 |
--------------------------------------------------------------------------------
/canopen_utils/resource/canopen_utils:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ros-industrial/ros2_canopen/f144f280f8e3c3f47491ae15e7f44ece1781db1a/canopen_utils/resource/canopen_utils
--------------------------------------------------------------------------------
/canopen_utils/setup.cfg:
--------------------------------------------------------------------------------
1 | [develop]
2 | script_dir=$base/lib/canopen_utils
3 | [install]
4 | install_scripts=$base/lib/canopen_utils
5 |
--------------------------------------------------------------------------------
/canopen_utils/setup.py:
--------------------------------------------------------------------------------
1 | # Copyright 2023 ROS-Industrial
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 | from setuptools import setup
16 |
17 | package_name = "canopen_utils"
18 |
19 | setup(
20 | name=package_name,
21 | version="0.3.0",
22 | packages=[package_name],
23 | data_files=[
24 | ("share/ament_index/resource_index/packages", ["resource/" + package_name]),
25 | ("share/" + package_name, ["package.xml"]),
26 | ],
27 | install_requires=["setuptools"],
28 | zip_safe=True,
29 | maintainer="christoph",
30 | maintainer_email="christoph.hellmann.santos@ipa.fraunhofer.de",
31 | description="TODO: Package description",
32 | license="Apache-2.0",
33 | tests_require=["pytest"],
34 | entry_points={
35 | "console_scripts": [
36 | "cyclic_tester = canopen_utils.cyclic_tester:main",
37 | "simple_tester = canopen_utils.simple_rpdo_tpdo_tester:main",
38 | ],
39 | },
40 | )
41 |
--------------------------------------------------------------------------------
/lely_core_libraries/CHANGELOG.rst:
--------------------------------------------------------------------------------
1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 | Changelog for package lely_core_libraries
3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4 |
5 | 0.2.9 (2024-04-16)
6 | ------------------
7 | * Update the lely_core_libraries hash to the latest.
8 | * Contributors: Chris Lalancette, Vishnuprasad Prachandabhanu
9 |
10 | 0.3.0 (2024-12-12)
11 | ------------------
12 | * Add yaml dependency to package.xml of `lely_core_libraries` (`#290 `_)
13 |
14 | 0.2.12 (2024-04-22)
15 | -------------------
16 | * 0.2.9
17 | * forthcoming
18 | * Merge pull request `#267 `_ from clalancette/clalancette/update-lely-core-hash
19 | Update the lely_core_libraries hash to the latest.
20 | * Update the lely_core_libraries hash to the latest.
21 | This will fix the building of the lely_core_libraries
22 | on Ubuntu 24.04.
23 | * Contributors: Chris Lalancette, Vishnuprasad Prachandabhanu, ipa-vsp
24 |
25 | 0.2.8 (2024-01-19)
26 | ------------------
27 |
28 | 0.2.7 (2023-06-30)
29 | ------------------
30 | * Add missing license headers and activate ament_copyright
31 | * Fix python versions
32 | * Contributors: Christoph Hellmann Santos
33 |
34 | 0.2.6 (2023-06-24)
35 | ------------------
36 | * Move install from external project to cmake main
37 | * Contributors: Christoph Hellmann Santos
38 |
39 | 0.2.5 (2023-06-23)
40 | ------------------
41 | * Directly install lely
42 | * Contributors: Christoph Hellmann Santos
43 |
44 | 0.2.4 (2023-06-22)
45 | ------------------
46 | * Add empy dependency for dcfgen
47 | * Clean up lely build folder after install for rpm build
48 | * Contributors: Christoph Hellmann Santos
49 |
50 | 0.2.3 (2023-06-22)
51 | ------------------
52 | * Fix manual dcfgen python installation on buildfarm
53 | * Solve buildfarm dependency issues
54 | * Contributors: Christoph Hellmann Santos
55 |
56 | 0.2.2 (2023-06-21)
57 | ------------------
58 | * Reset hard before patch applicaiton
59 | * Contributors: Christoph Hellmann Santos
60 |
61 | 0.2.1 (2023-06-21)
62 | ------------------
63 | * Do not build dcf-tools bdist in lely_core_libraries anymore, fixes buildfarm issue
64 | * Contributors: Christoph Hellmann Santos
65 |
66 | 0.2.0 (2023-06-14)
67 | ------------------
68 | * Created package
69 | * Contributors: Błażej Sowa, Christoph Hellmann Santos
70 |
--------------------------------------------------------------------------------
/lely_core_libraries/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.8)
2 | project(lely_core_libraries)
3 | find_package(ament_cmake REQUIRED)
4 | find_package(ament_cmake_python REQUIRED)
5 | set(python_version "python${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR}")
6 |
7 | include(ExternalProject)
8 | ExternalProject_Add(upstr_lely_core_libraries # Name for custom target
9 | #--Download step--------------
10 | SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/upstream
11 | INSTALL_DIR "${CMAKE_INSTALL_PREFIX}" # Installation prefix
12 | BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/build
13 | GIT_REPOSITORY https://gitlab.com/lely_industries/lely-core.git
14 | GIT_TAG fb735b79cab5f0cdda45bc5087414d405ef8f3ab
15 | TIMEOUT 60
16 | #UPDATE step apply patch to fix dcf-tools install
17 | UPDATE_COMMAND
18 | COMMAND git reset --hard
19 | COMMAND git apply --whitespace=fix --reject ${CMAKE_CURRENT_SOURCE_DIR}/patches/0001-Fix-dcf-tools.patch
20 | #CONFIGURE step execute autoreconf and configure
21 | CONFIGURE_COMMAND autoreconf -i
22 | COMMAND /configure --prefix= --disable-cython --disable-doc --disable-tests --disable-static --disable-diag
23 | #BUILD STEP execute make
24 | BUILD_COMMAND $(MAKE) -C ${CMAKE_CURRENT_BINARY_DIR}/build
25 | #INSTALL STEP do nothing as we install in main
26 | INSTALL_COMMAND ""
27 | )
28 |
29 | #INSTALL lely_core_libraries - execute make install
30 | install(CODE "execute_process(COMMAND ${CMAKE_MAKE_PROGRAM} install VERBOSE=1 WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/build)")
31 |
32 | set(lely_core_cmake_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
33 | include("cmake/lely_core_libraries-extras.cmake" NO_POLICY_SCOPE)
34 |
35 |
36 | install(
37 | DIRECTORY cmake
38 | DESTINATION share/${PROJECT_NAME}
39 | )
40 |
41 | ament_python_install_package(cogen SCRIPTS_DESTINATION lib/cogen)
42 |
43 | # install entry-point script(s) in bin as well
44 | install(
45 | DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/ament_cmake_python/cogen/scripts/
46 | DESTINATION ${CMAKE_INSTALL_PREFIX}/bin/
47 | USE_SOURCE_PERMISSIONS)
48 |
49 | ament_export_include_directories(include)
50 | ament_export_libraries(lely-can lely-co lely-coapp lely-ev lely-io2 lely-libc lely-tap lely-util)
51 | ament_package(
52 | CONFIG_EXTRAS
53 | "cmake/lely_core_libraries-extras.cmake"
54 | )
55 |
--------------------------------------------------------------------------------
/lely_core_libraries/cogen/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ros-industrial/ros2_canopen/f144f280f8e3c3f47491ae15e7f44ece1781db1a/lely_core_libraries/cogen/__init__.py
--------------------------------------------------------------------------------
/lely_core_libraries/cogen/cogen.py:
--------------------------------------------------------------------------------
1 | # Copyright 2022 Christoph Hellmann Santos
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 | import yaml
16 | import argparse
17 | from dataclasses import dataclass
18 | from dcfgen.cli import Master, Slave
19 |
20 |
21 | def main():
22 | parser = argparse.ArgumentParser(
23 | description="Expands the CANopen bus.yml for further processing."
24 | )
25 | parser.add_argument("--input-file", type=str, help="The name of the input file", required=True)
26 | parser.add_argument(
27 | "--output-file", type=str, help="The name of the output file", required=True
28 | )
29 | args = parser.parse_args()
30 |
31 | with open(args.input_file) as input:
32 | cfg = yaml.load(input, yaml.FullLoader)
33 |
34 | master = {}
35 | if "master" not in cfg:
36 | print("Found no master.")
37 | return
38 | else:
39 | master = cfg["master"]
40 |
41 | nodes = {}
42 | if "nodes" not in cfg:
43 | print("Found no nodes entry.")
44 | return
45 | else:
46 | nodes = cfg["nodes"]
47 |
48 | options = {}
49 | if "options" in cfg:
50 | options = cfg["options"]
51 |
52 | defaults = {}
53 | if "defaults" in cfg:
54 | defaults = cfg["defaults"]
55 |
56 | # add defaults to each node
57 | for node_name in nodes:
58 | for entry_name in defaults:
59 | nodes[node_name][entry_name] = defaults[entry_name]
60 |
61 | modified_file = {}
62 | modified_file["options"] = options
63 | # modified_file["defaults"] = defaults
64 | modified_file["master"] = master
65 | for node_name in nodes:
66 | modified_file[node_name] = nodes[node_name]
67 |
68 | with open(args.output_file, mode="w") as output:
69 | yaml.dump(modified_file, output)
70 |
71 | return
72 |
73 |
74 | if __name__ == "__main__":
75 | main()
76 |
--------------------------------------------------------------------------------
/lely_core_libraries/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | lely_core_libraries
5 | 0.3.0
6 |
7 | ROS wrapper for lely-core-libraries
8 |
9 | Christoph Hellmann Santos
10 | Apache-2.0
11 |
12 | ament_cmake
13 | git
14 | autoconf
15 | automake
16 | libtool
17 | python3-empy
18 | python3-yaml
19 |
20 |
21 | ament_cmake
22 |
23 |
24 |
--------------------------------------------------------------------------------
/lely_core_libraries/setup.cfg:
--------------------------------------------------------------------------------
1 | [options.entry_points]
2 | console_scripts =
3 | cogen = cogen.cogen:main
4 |
--------------------------------------------------------------------------------