Full Code of ros-industrial/ros2_canopen for AI

master ace7db77c935 cached
340 files
1.5 MB
435.4k tokens
859 symbols
1 requests
Download .txt
Showing preview only (1,641K chars total). Download the full file or copy to clipboard to get everything.
Repository: ros-industrial/ros2_canopen
Branch: master
Commit: ace7db77c935
Files: 340
Total size: 1.5 MB

Directory structure:
gitextract_xhwsmvzo/

├── .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
│       ├── prerelease-rolling.yml
│       ├── rolling.yml
│       └── rolling_documentation.yml
├── .gitignore
├── .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
│       ├── 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/
│           │   ├── managed-service-interface.rst
│           │   ├── ros2-control-interface.rst
│           │   └── service-interface.rst
│           ├── operation.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_multichannel_system/
│   │   │   ├── README.md
│   │   │   ├── bus.yml
│   │   │   └── ros2_controllers.yaml
│   │   ├── 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

================================================
FILE CONTENTS
================================================

================================================
FILE: .clang-format
================================================
---
Language: Cpp
BasedOnStyle: Google

AccessModifierOffset: -2
AlignAfterOpenBracket: AlwaysBreak
BreakBeforeBraces: Allman
ColumnLimit: 100
ConstructorInitializerIndentWidth: 0
ContinuationIndentWidth: 2
IndentWidth: 2
TabWidth: 2
DerivePointerAlignment: false
PointerAlignment: Middle
ReflowComments: true
IncludeBlocks: Preserve
...


================================================
FILE: .codespellignore
================================================
ons


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''

---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior

**Expected behavior**
A clear and concise description of what you expected to happen.

**Logs**

**Setup:**
 - Device:
 - OS:
 - ROS-Distro:
 - Branch/Commit:

**Additional context**
Add any other context about the problem here.


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: ''

---

**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
A clear and concise description of what you want to happen.

**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.

**Additional context**
Add any other context or screenshots about the feature request here.


================================================
FILE: .github/ISSUE_TEMPLATE/question.md
================================================
---
name: Question
about: Create a report to help us improve
title: ''
labels: question
assignees: ''

---

**Describe the bug**
A clear and concise description of what the bug is.

**Logs**
Add build or execution log for context.

**Setup:**
 - Device:
 - OS:
 - ROS-Distro:
 - Branch/Commit:

**Additional context**
Add any other context about the problem here.


================================================
FILE: .github/dependabot.yaml
================================================
# Set update schedule for GitHub Actions

version: 2
updates:

  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      # Check for updates to GitHub Actions every week
      interval: "weekly"


================================================
FILE: .github/workflows/ci-format.yml
================================================
# This is a format job. Pre-commit has a first-party GitHub action, so we use
# that: https://github.com/pre-commit/action

name: Pre-commit Format

on:
  workflow_dispatch:
  pull_request:

jobs:
  pre-commit:
    name: Format
    runs-on: ubuntu-22.04
    steps:
    - uses: actions/checkout@v6
    - uses: actions/setup-python@v6
      with:
        python-version: 3.10.6
    - name: Install system hooks
      run: sudo apt update && sudo apt install -qq clang-format-14 cppcheck
    - uses: pre-commit/action@v3.0.1
      with:
        extra_args: --all-files --hook-stage manual


================================================
FILE: .github/workflows/ci-ros-lint.yml.backup
================================================
name: ROS Lint
on:
  pull_request:

jobs:
  ament_lint:
    name: ament_${{ matrix.linter }}
    runs-on: ubuntu-20.04
    strategy:
      fail-fast: false
      matrix:
          linter: [cppcheck, copyright, lint_cmake]
    steps:
    - uses: actions/checkout@v3
    - uses: ros-tooling/setup-ros@v0.2
    - uses: ros-tooling/action-ros-lint@v0.1
      with:
        distribution: rolling
        linter: ${{ matrix.linter }}
        package-name:
          $PKG_NAME$

  ament_lint_100:
    name: ament_${{ matrix.linter }}
    runs-on: ubuntu-20.04
    strategy:
      fail-fast: false
      matrix:
          linter: [cpplint]
    steps:
    - uses: actions/checkout@v3
    - uses: ros-tooling/setup-ros@v0.2
    - uses: ros-tooling/action-ros-lint@v0.1
      with:
        distribution: rolling
        linter: cpplint
        arguments: "--linelength=100 --filter=-whitespace/newline"
        package-name:
          ros2_canopen


================================================
FILE: .github/workflows/docker.yml
================================================
name: Create and publish a Docker image
on:
  push:
    branches: ['master']
  workflow_dispatch:

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build-and-push-image:
    runs-on: ubuntu-22.04

    permissions:
      contents: read
      packages: write

    steps:
      - name: Checkout repository
        uses: actions/checkout@v6
      - name: Log in to the Container registry
        uses: docker/login-action@v4
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract metadata (tags, labels) for Docker
        id: meta
        uses: docker/metadata-action@v6
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

      - name: Build and push Docker image
        uses: docker/build-push-action@v7
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}


================================================
FILE: .github/workflows/humble.yml
================================================
name: Industrial CI Humble

on:
  push:
    branches: [ humble ]
  pull_request:
    branches: [ humble ]
  workflow_dispatch:

jobs:
  industrial_ci:
    name: ROS ${{ matrix.ROS_DISTRO }} (${{ matrix.ROS_REPO }})
    runs-on: ubuntu-22.04
    strategy:
      fail-fast: false
      matrix:
        ROS_DISTRO: [humble]
        ROS_REPO: [testing]
    env:
      CCACHE_DIR: "${{ github.workspace }}/.ccache"
    steps:
      - uses: actions/checkout@v6
      - uses: actions/cache@v4
        with:
          path: ${{ env.CCACHE_DIR }}
          key: ccache-${{ matrix.ROS_DISTRO }}-${{ matrix.ROS_REPO }}-${{github.run_id}}
          restore-keys: |
            ccache-${{ matrix.ROS_DISTRO }}-${{ matrix.ROS_REPO }}-
      - uses: 'ros-industrial/industrial_ci@master'
        env:
          BEFORE_INSTALL_TARGET_DEPENDENCIES: 'sudo apt-get update'
          ROS_DISTRO: ${{ matrix.ROS_DISTRO }}
          ROS_REPO: ${{ matrix.ROS_REPO }}


================================================
FILE: .github/workflows/humble_documentation.yml
================================================
name: Documentation Humble

# Controls when the workflow will run
on:
  # Triggers the workflow on push or pull request events but only for the master branch
  push:
    branches: [ humble ]
    paths:
      - 'canopen/**'
      - '.github/workflows/humble_documentation.yml'

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  build_documentation:
    # The type of runner that the job will run on
    runs-on: ubuntu-22.04

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v6

      - name: Install dependencies
        run: |
            sudo apt-get update -qq
            sudo apt-get install -y -qq doxygen graphviz plantuml
            pip install sphinx-rtd-theme
            pip install sphinxcontrib-plantuml
            pip install sphinx-mdinclude
            pip install breathe
            pip install exhale

      - name: Build doxygen
        run: |
            cd ./canopen/doxygen/
            doxygen
            cd ../..

      - name: Build documentation
        run: |
            cd ./canopen/sphinx/
            make html
            cd ../..

      - name: Create commit
        run: |
            git clone https://github.com/ros-industrial/ros2_canopen.git --branch gh-pages --single-branch gh-pages
            mkdir -p gh-pages/manual/humble/
            mkdir -p gh-pages/api/humble/
            cp -r ./canopen/sphinx/_build/html/* gh-pages/manual/humble/
            cp -r ./canopen/doxygen/_build/html/* gh-pages/api/humble/
            cd gh-pages
            git config --local user.email "action@github.com"
            git config --local user.name "GitHub Action"
            git add .
            git commit -m "Update documentation" -a || true

      - name: Push changes
        uses: ad-m/github-push-action@master
        with:
          branch: gh-pages
          directory: gh-pages
          github_token: ${{ secrets.GITHUB_TOKEN }}


================================================
FILE: .github/workflows/prerelease-rolling.yml
================================================
name: Prerelease-Test Rolling

on:
  workflow_dispatch:
  push:
    tags:
      - "*"

jobs:
  industrial_ci:
    name: ROS ${{ matrix.ROS_DISTRO }} (${{ matrix.ROS_REPO }})
    runs-on: ubuntu-22.04
    strategy:
      fail-fast: false
      matrix:
        ROS_DISTRO: [rolling]
        ROS_REPO: [testing]
    steps:
      - uses: actions/checkout@v6
      - uses: 'ros-industrial/industrial_ci@master'
        env:
          BEFORE_INSTALL_TARGET_DEPENDENCIES: 'sudo apt-get update'
          AFTER_BUILD_TARGET_WORKSPACE: 'set +u && COLCON_TRACE=0 AMENT_TRACE_SETUP_FILES=0 source /root/target_ws/install/setup.bash && set -u'
          ROS_DISTRO: ${{ matrix.ROS_DISTRO }}
          ROS_REPO: ${{ matrix.ROS_REPO }}
          PRERELEASE: true


================================================
FILE: .github/workflows/rolling.yml
================================================
name: Industrial CI

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]
  workflow_dispatch:

jobs:
  industrial_ci:
    name: ROS ${{ matrix.ROS_DISTRO }} (${{ matrix.ROS_REPO }})
    runs-on: ubuntu-24.04
    strategy:
      fail-fast: false
      matrix:
        include:
          - ROS_DISTRO: rolling
            ROS_REPO: testing
          - ROS_DISTRO: jazzy
            ROS_REPO: testing
          - ROS_DISTRO: kilted
            ROS_REPO: testing
    env:
      CCACHE_DIR: "${{ github.workspace }}/.ccache"
    steps:
      - uses: actions/checkout@v6
      - uses: actions/cache@v4
        with:
          path: ${{ env.CCACHE_DIR }}
          key: ccache-${{ matrix.ROS_DISTRO }}-${{ matrix.ROS_REPO }}-${{github.run_id}}
          restore-keys: |
            ccache-${{ matrix.ROS_DISTRO }}-${{ matrix.ROS_REPO }}-
      - uses: 'ros-industrial/industrial_ci@master'
        if: ${{ github.event_name != 'pull_request' || matrix.ROS_DISTRO == 'rolling' }}
        env:
          BEFORE_INSTALL_TARGET_DEPENDENCIES: 'sudo apt-get update'
          AFTER_BUILD_TARGET_WORKSPACE: 'set +u && COLCON_TRACE=0 AMENT_TRACE_SETUP_FILES=0 source /root/target_ws/install/setup.bash && set -u'
          ROS_DISTRO: ${{ matrix.ROS_DISTRO }}
          ROS_REPO: ${{ matrix.ROS_REPO }}
          PRERELEASE: false


================================================
FILE: .github/workflows/rolling_documentation.yml
================================================
name: Documentation

# Controls when the workflow will run
on:
  # Triggers the workflow on push or pull request events but only for the master branch
  push:
    branches: [ master ]
    paths:
      - 'canopen/**'
      - '.github/workflows/rolling_documentation.yml'

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  build_documentation:
    # The type of runner that the job will run on
    runs-on: ubuntu-24.04
    strategy:
      fail-fast: false
      matrix:
        ROS_DISTRO: [rolling, jazzy, kilted]

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v6

      - name: Install dependencies
        run: |
            sudo apt-get update -qq
            sudo apt-get install -y -qq doxygen graphviz plantuml
            pip install sphinx-rtd-theme
            pip install sphinxcontrib-plantuml
            pip install sphinx-mdinclude
            pip install breathe
            pip install exhale

      - name: Build doxygen
        run: |
            cd ./canopen/doxygen/
            doxygen
            cd ../..

      - name: Build documentation
        run: |
            cd ./canopen/sphinx/
            make html
            cd ../..

      - name: Create commit
        run: |
            git clone https://github.com/ros-industrial/ros2_canopen.git --branch gh-pages --single-branch gh-pages
            mkdir -p gh-pages/manual/${{ matrix.ROS_DISTRO }}/
            mkdir -p gh-pages/api/${{ matrix.ROS_DISTRO }}/
            cp -r ./canopen/sphinx/_build/html/* gh-pages/manual/${{ matrix.ROS_DISTRO }}/
            cp -r ./canopen/doxygen/_build/html/* gh-pages/api/${{ matrix.ROS_DISTRO }}/
            cd gh-pages
            git config --local user.email "action@github.com"
            git config --local user.name "GitHub Action"
            git add .
            git commit -m "Update documentation" -a || true

      - name: Push changes
        uses: ad-m/github-push-action@master
        with:
          branch: gh-pages
          directory: gh-pages
          github_token: ${{ secrets.GITHUB_TOKEN }}


================================================
FILE: .gitignore
================================================
.vscode/
**/doc_output/
**/__pycache__/
**/_build
**/api


================================================
FILE: .pre-commit-config.yaml
================================================
# To use:
#
#     pre-commit run -a
#
# Or:
#
#     pre-commit install  # (runs every time you commit in git)
#
# To update this file:
#
#     pre-commit autoupdate
#
# See https://github.com/pre-commit/pre-commit
exclude: '.*\.patch'
repos:
  # Standard hooks
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.6.0
    hooks:
      - id: check-added-large-files
      - id: check-ast
      - id: check-case-conflict
      - id: check-docstring-first
      - id: check-merge-conflict
      - id: check-symlinks
      - id: check-xml
      - id: check-yaml
        exclude: canopen_core/test/bus_configs/bad_driver_duplicate.yml
      - id: debug-statements
      - id: end-of-file-fixer
      - id: mixed-line-ending
      - id: trailing-whitespace
      - id: fix-byte-order-marker

  # Python hooks
  - repo: https://github.com/asottile/pyupgrade
    rev: v3.17.0
    hooks:
    -   id: pyupgrade
        args: [--py36-plus]

  - repo: https://github.com/psf/black
    rev: 24.8.0
    hooks:
      - id: black
        args: ["--line-length=99"]

  # CPP hooks
  - repo: local
    hooks:
      - id: clang-format
        name: clang-format
        description: Format files with ClangFormat.
        entry: clang-format-14
        language: system
        files: \.(c|cc|cxx|cpp|frag|glsl|h|hpp|hxx|ih|ispc|ipp|java|js|m|proto|vert)$
        args: ['-fallback-style=none', '-i']

  # Cmake hooks
  # - repo: local
  #   hooks:
  #     - id: ament_lint_cmake
  #       name: ament_lint_cmake
  #       description: Check format of CMakeLists.txt files.
  #       stages: [commit]
  #       entry: ament_lint_cmake
  #       language: system
  #       files: CMakeLists\.txt$
  #       exclude: lely_core_libraries\/CMakeLists\.txt$

  # # Copyright
  - repo: local
    hooks:
      - id: ament_copyright
        name: ament_copyright
        description: Check if copyright notice is available in all files.
        stages: [commit]
        entry: ament_copyright
        args: ["--add-missing", "ROS-Industrial", "apache2"]
        language: system

  # Docs - RestructuredText hooks
  - repo: https://github.com/PyCQA/doc8
    rev: v1.1.1
    hooks:
      - id: doc8
        args: ['--max-line-length=100', '--ignore=D001']
        exclude: CHANGELOG\.rst$

  - repo: https://github.com/pre-commit/pygrep-hooks
    rev: v1.10.0
    hooks:
      - id: rst-backticks
        exclude: CHANGELOG\.rst$
      - id: rst-directive-colons
      - id: rst-inline-touching-normal

  # Spellcheck in comments and docs
  # skipping of *.svg files is not working...
  - repo: https://github.com/codespell-project/codespell
    rev: v2.2.1
    hooks:
      - id: codespell
        args: ['--write-changes', '-I', '.codespellignore']
        exclude: CHANGELOG\.rst|\.(svg|pyc|drawio|dcf|eds)$


================================================
FILE: Dockerfile
================================================
FROM ros:rolling-ros-core


RUN apt-get update \
    && apt-get install -y \
        python3-rosdep \
        python3-argcomplete \
        python3-colcon-common-extensions \
        build-essential \
        pkg-config \
        python3-wheel

WORKDIR /home/can_ws/src
COPY . ros2_canopen

WORKDIR /home/can_ws/
RUN . /opt/ros/rolling/setup.sh \
    && rosdep init && rosdep update \
    && rosdep install --from-paths src --ignore-src -r -y \
    && colcon build \
    && . install/setup.sh


================================================
FILE: README.md
================================================
# ROS2 CANopen

## Status

| Build Process | Status |
|---------------|--------|
| Industrial CI Build | [![Industrial CI](https://github.com/ros-industrial/ros2_canopen/actions/workflows/rolling.yml/badge.svg)](https://github.com/ros-industrial/ros2_canopen/actions/workflows/rolling.yml) |
| Documentation Build | [![Documentation](https://github.com/ros-industrial/ros2_canopen/actions/workflows/rolling_documentation.yml/badge.svg)](https://github.com/ros-industrial/ros2_canopen/actions/workflows/rolling_documentation.yml) |
| Buildfarm Build (rolling) | [![Buildfarm Status](https://build.ros2.org/job/Rdev__ros2_canopen__ubuntu_noble_amd64/badge/icon)](https://build.ros2.org/job/Rdev__ros2_canopen__ubuntu_noble_amd64/) |
| Buildfarm Build (kilted) | [![Buildfarm Status](https://build.ros2.org/job/Kdev__ros2_canopen__ubuntu_noble_amd64/badge/icon)](https://build.ros2.org/job/Kdev__ros2_canopen__ubuntu_noble_amd64/) |
| Buildfarm Build (jazzy) | [![Buildfarm Status](https://build.ros2.org/job/Jdev__ros2_canopen__ubuntu_noble_amd64/badge/icon)](https://build.ros2.org/job/Jdev__ros2_canopen__ubuntu_noble_amd64/) |

The stack is currently under development and not yet ready for production use.

## Documentation
The documentation consists of two parts: a manual and an api reference.
The documentation is built for rolling (master), kilted, jazzy, iron and humble and hosted on github pages.
Older ROS 2 releases are EOL and are not supported anymore.

***Note:** Master branch works with ROS2 **Jazzy**, **Kilted** and **Rolling** distributions. For **Humble** distribution use the `humble` branch.*

### Rolling
* Manual: https://ros-industrial.github.io/ros2_canopen/manual/rolling/
* API reference: https://ros-industrial.github.io/ros2_canopen/api/rolling/

### Humble
* Manual: https://ros-industrial.github.io/ros2_canopen/manual/humble/
* API reference: https://ros-industrial.github.io/ros2_canopen/api/humble/

## Features
These are some of the features this stack implements. For further information please refer to the documentation.

* **YAML-Bus configuration**
  This canopen stack enables you to configure the bus using a YAML file. In this file you define the nodes that are connected to the bus by specifying their node id, the corresponding EDS file and the driver to run for the node. You can also specify further parameters that overwrite EDS parameters or are inputs to the driver.
* **Service based operation**
  The stack can be operated using standard ROS2 nodes. In this case the device container will load the drivers for master and slave nodes. Each driver will be visible as a
  node and expose a ROS 2 interface. All drivers are brought up when the device manager is launched.
* **Managed service based operation**
  The stack can be opeprated using managed ROS2 nodes. In
  this case the device container will load the drivers for master and slave nodes based on the bus configuration. Each driver will be a lifecycle node and expose a ROS 2 interface. The lifecycle manager can be used to bring all
  device up and down in the correct sequence.
* **ROS2 control based operation**
  Currently, multiple ros2_control interfaces are available. These can be used for controlling CANopen devices. The interfaces are:
  * canopen_ros2_control/CANopenSystem
  * canopen_ros2_control/CIA402System
  * canopen_ros2_control/RobotSystem
* **CANopen drivers**
  Currently, the following drivers are available:
    * ProxyDriver
    * Cia402Driver


## Post testing
To test stack after it was built from source you should first setup a virtual can network.
```bash
sudo modprobe vcan
sudo ip link add dev vcan0 type vcan
sudo ip link set vcan0 txqueuelen 1000
sudo ip link set up vcan0
```
Then you can launch a managed example
```bash
ros2 launch canopen_tests cia402_lifecycle_setup.launch.py
ros2 lifecycle set /lifecycle_manager configure
ros2 lifecycle set /lifecycle_manager activate
```

Or you can launch a standard example
```bash
ros2 launch canopen_tests cia402_setup.launch.py
```

Or you can launch a ros2_control example
```bash
ros2 launch canopen_tests robot_control_setup.launch.py
```

## Contributing
This repository uses `pre-commit` for code formatting.
This program has to be setup locally and installed inside the repository.
For this execute in the repository folder following commands:
```
sudo apt install -y pre-commit
pre-commit install
```
The checks are automatically executed before each commit.
This helps you to always commit well formatted code.
To run all the checks manually use `pre-commit run -a` command.
For the other options check `pre-commit --help`.

In a case of an "emergency" you can avoid execution of pre-commit hooks by adding `-n` flag to `git commit` command - this is NOT recommended to do if you don't know what are you doing!

## Rolling Distribution (Noble & RHEL9)

| Package                  | Noble (Ubuntu)                                                                                                                  | RHEL9                                                                                                                            |
|--------------------------|---------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------|
| canopen_interfaces       | [![Build Status](https://build.ros2.org/job/Rbin_uN64__canopen_interfaces__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Rbin_uN64__canopen_interfaces__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Rbin_rhel_el964__canopen_interfaces__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Rbin_rhel_el964__canopen_interfaces__rhel_9_x86_64__binary/) |
| lely_core_libraries      | [![Build Status](https://build.ros2.org/job/Rbin_uN64__lely_core_libraries__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Rbin_uN64__lely_core_libraries__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Rbin_rhel_el964__lely_core_libraries__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Rbin_rhel_el964__lely_core_libraries__rhel_9_x86_64__binary/) |
| canopen_core             | [![Build Status](https://build.ros2.org/job/Rbin_uN64__canopen_core__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Rbin_uN64__canopen_core__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Rbin_rhel_el964__canopen_core__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Rbin_rhel_el964__canopen_core__rhel_9_x86_64__binary/) |
| canopen_master_driver    | [![Build Status](https://build.ros2.org/job/Rbin_uN64__canopen_master_driver__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Rbin_uN64__canopen_master_driver__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Rbin_rhel_el964__canopen_master_driver__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Rbin_rhel_el964__canopen_master_driver__rhel_9_x86_64__binary/) |
| canopen_base_driver      | [![Build Status](https://build.ros2.org/job/Rbin_uN64__canopen_base_driver__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Rbin_uN64__canopen_base_driver__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Rbin_rhel_el964__canopen_base_driver__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Rbin_rhel_el964__canopen_base_driver__rhel_9_x86_64__binary/) |
| canopen_proxy_driver     | [![Build Status](https://build.ros2.org/job/Rbin_uN64__canopen_proxy_driver__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Rbin_uN64__canopen_proxy_driver__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Rbin_rhel_el964__canopen_proxy_driver__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Rbin_rhel_el964__canopen_proxy_driver__rhel_9_x86_64__binary/) |
| canopen_402_driver       | [![Build Status](https://build.ros2.org/job/Rbin_uN64__canopen_402_driver__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Rbin_uN64__canopen_402_driver__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Rbin_rhel_el964__canopen_402_driver__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Rbin_rhel_el964__canopen_402_driver__rhel_9_x86_64__binary/) |
| canopen_ros2_control     | [![Build Status](https://build.ros2.org/job/Rbin_uN64__canopen_ros2_control__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Rbin_uN64__canopen_ros2_control__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Rbin_rhel_el964__canopen_ros2_control__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Rbin_rhel_el964__canopen_ros2_control__rhel_9_x86_64__binary/) |
| canopen_ros2_controllers | [![Build Status](https://build.ros2.org/job/Rbin_uN64__canopen_ros2_controllers__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Rbin_uN64__canopen_ros2_controllers__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Rbin_rhel_el964__canopen_ros2_controllers__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Rbin_rhel_el964__canopen_ros2_controllers__rhel_9_x86_64__binary/) |
| canopen_tests            | [![Build Status](https://build.ros2.org/job/Rbin_uN64__canopen_tests__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Rbin_uN64__canopen_tests__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Rbin_rhel_el964__canopen_tests__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Rbin_rhel_el964__canopen_tests__rhel_9_x86_64__binary/) |
| canopen_utils            | [![Build Status](https://build.ros2.org/job/Rbin_uN64__canopen_utils__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Rbin_uN64__canopen_utils__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Rbin_rhel_el964__canopen_utils__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Rbin_rhel_el964__canopen_utils__rhel_9_x86_64__binary/) |

## Kilted Distribution (Noble & RHEL9)
| Package                  | Noble (Ubuntu)                                                                                                                  | RHEL9                                                                                                                            |
|--------------------------|---------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------|
| canopen_interfaces       | [![Build Status](https://build.ros2.org/job/Kbin_uN64__canopen_interfaces__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Kbin_uN64__canopen_interfaces__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Kbin_rhel_el964__canopen_interfaces__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Kbin_rhel_el964__canopen_interfaces__rhel_9_x86_64__binary/) |
| lely_core_libraries      | [![Build Status](https://build.ros2.org/job/Kbin_uN64__lely_core_libraries__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Kbin_uN64__lely_core_libraries__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Kbin_rhel_el964__lely_core_libraries__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Kbin_rhel_el964__lely_core_libraries__rhel_9_x86_64__binary/) |
| canopen_core             | [![Build Status](https://build.ros2.org/job/Kbin_uN64__canopen_core__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Kbin_uN64__canopen_core__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Kbin_rhel_el964__canopen_core__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Kbin_rhel_el964__canopen_core__rhel_9_x86_64__binary/) |
| canopen_master_driver    | [![Build Status](https://build.ros2.org/job/Kbin_uN64__canopen_master_driver__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Kbin_uN64__canopen_master_driver__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Kbin_rhel_el964__canopen_master_driver__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Kbin_rhel_el964__canopen_master_driver__rhel_9_x86_64__binary/) |
| canopen_base_driver      | [![Build Status](https://build.ros2.org/job/Kbin_uN64__canopen_base_driver__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Kbin_uN64__canopen_base_driver__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Kbin_rhel_el964__canopen_base_driver__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Kbin_rhel_el964__canopen_base_driver__rhel_9_x86_64__binary/) |
| canopen_proxy_driver     | [![Build Status](https://build.ros2.org/job/Kbin_uN64__canopen_proxy_driver__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Kbin_uN64__canopen_proxy_driver__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Kbin_rhel_el964__canopen_proxy_driver__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Kbin_rhel_el964__canopen_proxy_driver__rhel_9_x86_64__binary/) |
| canopen_402_driver       | [![Build Status](https://build.ros2.org/job/Kbin_uN64__canopen_402_driver__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Kbin_uN64__canopen_402_driver__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Kbin_rhel_el964__canopen_402_driver__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Kbin_rhel_el964__canopen_402_driver__rhel_9_x86_64__binary/) |
| canopen_ros2_control     | [![Build Status](https://build.ros2.org/job/Kbin_uN64__canopen_ros2_control__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Kbin_uN64__canopen_ros2_control__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Kbin_rhel_el964__canopen_ros2_control__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Kbin_rhel_el964__canopen_ros2_control__rhel_9_x86_64__binary/) |
| canopen_ros2_controllers | [![Build Status](https://build.ros2.org/job/Kbin_uN64__canopen_ros2_controllers__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Kbin_uN64__canopen_ros2_controllers__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Kbin_rhel_el964__canopen_ros2_controllers__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Kbin_rhel_el964__canopen_ros2_controllers__rhel_9_x86_64__binary/) |
| canopen_tests            | [![Build Status](https://build.ros2.org/job/Kbin_uN64__canopen_tests__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Kbin_uN64__canopen_tests__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Kbin_rhel_el964__canopen_tests__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Kbin_rhel_el964__canopen_tests__rhel_9_x86_64__binary/) |
| canopen_utils            | [![Build Status](https://build.ros2.org/job/Kbin_uN64__canopen_utils__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Kbin_uN64__canopen_utils__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Kbin_rhel_el964__canopen_utils__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Kbin_rhel_el964__canopen_utils__rhel_9_x86_64__binary/) |

## Jazzy Distribution (Noble & RHEL9)
| Package                  | Noble (Ubuntu)                                                                                                                  | RHEL9                                                                                                                            |
|--------------------------|---------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------|
| canopen_interfaces       | [![Build Status](https://build.ros2.org/job/Jbin_uN64__canopen_interfaces__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Jbin_uN64__canopen_interfaces__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Jbin_rhel_el964__canopen_interfaces__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Jbin_rhel_el964__canopen_interfaces__rhel_9_x86_64__binary/) |
| lely_core_libraries      | [![Build Status](https://build.ros2.org/job/Jbin_uN64__lely_core_libraries__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Jbin_uN64__lely_core_libraries__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Jbin_rhel_el964__lely_core_libraries__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Jbin_rhel_el964__lely_core_libraries__rhel_9_x86_64__binary/) |
| canopen_core             | [![Build Status](https://build.ros2.org/job/Jbin_uN64__canopen_core__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Jbin_uN64__canopen_core__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Jbin_rhel_el964__canopen_core__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Jbin_rhel_el964__canopen_core__rhel_9_x86_64__binary/) |
| canopen_master_driver    | [![Build Status](https://build.ros2.org/job/Jbin_uN64__canopen_master_driver__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Jbin_uN64__canopen_master_driver__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Jbin_rhel_el964__canopen_master_driver__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Jbin_rhel_el964__canopen_master_driver__rhel_9_x86_64__binary/) |
| canopen_base_driver      | [![Build Status](https://build.ros2.org/job/Jbin_uN64__canopen_base_driver__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Jbin_uN64__canopen_base_driver__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Jbin_rhel_el964__canopen_base_driver__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Jbin_rhel_el964__canopen_base_driver__rhel_9_x86_64__binary/) |
| canopen_proxy_driver     | [![Build Status](https://build.ros2.org/job/Jbin_uN64__canopen_proxy_driver__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Jbin_uN64__canopen_proxy_driver__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Jbin_rhel_el964__canopen_proxy_driver__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Jbin_rhel_el964__canopen_proxy_driver__rhel_9_x86_64__binary/) |
| canopen_402_driver       | [![Build Status](https://build.ros2.org/job/Jbin_uN64__canopen_402_driver__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Jbin_uN64__canopen_402_driver__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Jbin_rhel_el964__canopen_402_driver__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Jbin_rhel_el964__canopen_402_driver__rhel_9_x86_64__binary/) |
| canopen_ros2_control     | [![Build Status](https://build.ros2.org/job/Jbin_uN64__canopen_ros2_control__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Jbin_uN64__canopen_ros2_control__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Jbin_rhel_el964__canopen_ros2_control__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Jbin_rhel_el964__canopen_ros2_control__rhel_9_x86_64__binary/) |
| canopen_ros2_controllers | [![Build Status](https://build.ros2.org/job/Jbin_uN64__canopen_ros2_controllers__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Jbin_uN64__canopen_ros2_controllers__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Jbin_rhel_el964__canopen_ros2_controllers__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Jbin_rhel_el964__canopen_ros2_controllers__rhel_9_x86_64__binary/) |
| canopen_tests            | [![Build Status](https://build.ros2.org/job/Jbin_uN64__canopen_tests__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Jbin_uN64__canopen_tests__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Jbin_rhel_el964__canopen_tests__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Jbin_rhel_el964__canopen_tests__rhel_9_x86_64__binary/) |
| canopen_utils            | [![Build Status](https://build.ros2.org/job/Jbin_uN64__canopen_utils__ubuntu_noble_amd64__binary/badge/icon)](https://build.ros2.org/job/Jbin_uN64__canopen_utils__ubuntu_noble_amd64__binary/) | [![Build Status](https://build.ros2.org/job/Jbin_rhel_el964__canopen_utils__rhel_9_x86_64__binary/badge/icon)](https://build.ros2.org/job/Jbin_rhel_el964__canopen_utils__rhel_9_x86_64__binary/) |


================================================
FILE: canopen/CHANGELOG.rst
================================================
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Changelog for package canopen
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

0.3.2 (2025-12-05)
------------------
* add pdo 6077 torque actual value to the joint state interface as effort (`#316 <https://github.com/ros-industrial/ros2_canopen/issues/316>`_)
* Fix configuration parsing and logging
* Refactor on_init method for improved readability and consistency
* Fix deprecated hardware_interface API (`#386 <https://github.com/ros-industrial/ros2_canopen/issues/386>`_)
* Fix typos in warning messages and comments for clarity
* `#379 <https://github.com/ros-industrial/ros2_canopen/issues/379>`_: Fix data conversion in the Lely Bridge to enable more data types and proper handling of Emcy in ros2_control
* Return error on Emcy and add correct data conversion for Emcy
* Fixed types handling in canopen_ros2_control and optimized debug output
* Fixed sending values
* `#376 <https://github.com/ros-industrial/ros2_canopen/issues/376>`_: increase boot timeout
* `#400 <https://github.com/ros-industrial/ros2_canopen/issues/400>`_: Update controllers for ROS Rolling API changes and fix fake slave type handling
* Refactor GetValue method to use std::type_index for type comparisons
* `motion_generator` as shared library (`#295 <https://github.com/ros-industrial/ros2_canopen/issues/295>`_)
* Enhance SimpleSlave class with vendor ID parsing and adjust bus configuration timeouts
* Multiple SDO types for slaves (`#278 <https://github.com/ros-industrial/ros2_canopen/issues/278>`_)
* Enhance command interface error handling and feedback reporting in CanopenProxyController
* Contributors: Christoph Fröhlich, Christoph Hellmann Santos, Dr. Denis Stogl, Patrick Roncagliolo, Vishnuprasad Prachandabhanu, synsi23b

0.3.1 (2025-06-23)
------------------
* Sync upstream 'master' into homing_timeout_pr.
  Fix homing info message to include both offset
  and homing timeout information.
* Add namespacing support
* Contributors: Vishnuprasad Prachandabhanu

0.3.0 (2024-12-12)
------------------
* Update CiA402 bus config docs
* Remove set heartbeat service from master documentation (`#294 <https://github.com/ros-industrial/ros2_canopen/issues/294>`_)
  Co-authored-by: Christoph Hellmann Santos <christoph.hellmann.santos@ipa.fraunhofer.de>
* Add cyclic torque mode to cia402 driver and robot system controller (`#293 <https://github.com/ros-industrial/ros2_canopen/issues/293>`_)
  * Add base functions for switching to cyclic torque mode
  * Add cyclic torque mode as effort interface to robot_system controller
  * Add documentation about cyclic torque mode.
  Co-authored-by: Christoph Hellmann Santos <christoph.hellmann.santos@ipa.fraunhofer.de>

0.2.12 (2024-04-22)
-------------------
* Merge pull request `#280 <https://github.com/ros-industrial/ros2_canopen/issues/280>`_ from ipa-vsp/fix/yaml-build-error
  Fix undefined reference to yaml library
* pre-commit update
* Merge pull request `#261 <https://github.com/ros-industrial/ros2_canopen/issues/261>`_ from gsalinas/configurable-sdo-timeout
  Configurable SDO timeout
* 0.2.9
* forthcoming
* Merge pull request `#272 <https://github.com/ros-industrial/ros2_canopen/issues/272>`_ from ros-industrial/ipa-vsp-patch-1
  Update maintainer list
* Update package.xml
* Merge pull request `#220 <https://github.com/ros-industrial/ros2_canopen/issues/220>`_ from ipa-vsp/feature/timeout-config
  Add timeouts
* Add SDO timeout to device config documentation.
* change from 100ms to 2000ms
* timeout for booting slave
* Contributors: Gerry Salinas, Vishnuprasad Prachandabhanu, ipa-vsp

0.2.8 (2024-01-19)
------------------
* Documentation: Fix launch file spelling (`#208 <https://github.com/ros-industrial/ros2_canopen/issues/208>`_)
* Documentation: Fix package creation command.  (`#176 <https://github.com/ros-industrial/ros2_canopen/issues/176>`_)
  * Fix package creation
  * Fixed bus.yml nodes list
  * docs: fixed launch file path in instructions
  Co-authored-by: waterlinux <water@gmail.com>
* Contributors: Lewe Christiansen, Vishnuprasad Prachandabhanu

0.2.9 (2024-04-16)
------------------
* Update maintainer list
* Update package.xml
* Add timeouts
* Contributors: Vishnuprasad Prachandabhanu

0.2.7 (2023-06-30)
------------------
* Update ros2_control docs.
* Contributors: Christoph Hellmann Santos, Dr. Denis, Xi Huang

0.2.6 (2023-06-24)
------------------

0.2.5 (2023-06-23)
------------------

0.2.4 (2023-06-22)
------------------

0.2.3 (2023-06-22)
------------------

0.2.2 (2023-06-21)
------------------

0.2.1 (2023-06-21)
------------------

0.2.0 (2023-06-14)
------------------
* Created package
* Contributors: Borong Yuan, Błażej Sowa, Christoph Hellmann Santos, Denis Štogl, Vishnuprasad Prachandabhanu


================================================
FILE: canopen/CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.8)
project(canopen NONE)
find_package(ament_cmake REQUIRED)
ament_package()


================================================
FILE: canopen/LICENSE
================================================
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright 2022 Christoph Hellmann Santos

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.


================================================
FILE: canopen/doxygen/Doxyfile
================================================
# All settings not listed here will use the Doxygen default values.

PROJECT_NAME           = "ros2_canopen"
PROJECT_NUMBER         = master
PROJECT_BRIEF          = "C++ ROS CANopen Library"

# Use these lines to include the generated logging.hpp (update install path if needed)
INPUT                  = ../../canopen_core/include ../../canopen_base_driver/include ../../canopen_402_driver/include ../../canopen_proxy_driver/include

RECURSIVE              = YES
OUTPUT_DIRECTORY       = _build

EXTRACT_ALL            = YES
SORT_MEMBER_DOCS       = NO

GENERATE_LATEX         = NO
GENERATE_XML           = YES

ENABLE_PREPROCESSING   = YES

DOT_GRAPH_MAX_NODES    = 101

FILE_PATTERNS = *.cpp *.h *.hpp *.md


================================================
FILE: canopen/package.xml
================================================
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
  <name>canopen</name>
  <version>0.3.2</version>
  <description>Meta-package aggregating the ros2_canopen packages and documentation</description>
  <maintainer email="christoph.hellmann.santos@ipa.fraunhofer.de">Christoph Hellmann Santos</maintainer>
  <maintainer email="vishnuprasad.prachandabhanu@ipa.fraunhofer.de">Vishnuprasad Prachandabhanu</maintainer>
  <license>Apache-2.0</license>

  <buildtool_depend>ament_cmake</buildtool_depend>
  <exec_depend>canopen_interfaces</exec_depend>
  <exec_depend>canopen_core</exec_depend>
  <exec_depend>canopen_base_driver</exec_depend>
  <exec_depend>lely_core_libraries</exec_depend>
  <exec_depend>canopen_proxy_driver</exec_depend>
  <exec_depend>canopen_base_driver</exec_depend>
  <exec_depend>canopen_402_driver</exec_depend>

  <export>
    <build_type>ament_cmake</build_type>
  </export>
</package>


================================================
FILE: canopen/sphinx/Makefile
================================================
# Minimal makefile for Sphinx documentation
#

# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS    ?=
SPHINXBUILD   ?= sphinx-build
SOURCEDIR     = .
BUILDDIR      = _build

# Put it first so that "make" without argument is like "make help".
help:
	@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

.PHONY: help Makefile clean

clean:
	rm -rf "_doxygen/" "api/"
	@$(SPHINXBUILD) -M clean "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
	@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)


================================================
FILE: canopen/sphinx/_static/css/custom.css
================================================

.wy-table-responsive table td,
.wy-table-responsive table th {
 white-space:normal;
}

tr {
    white-space: normal;
}

thead {
    white-space: normal;
}

table {
    white-space: normal;
}


================================================
FILE: canopen/sphinx/application/prbt_robot.rst
================================================
Pilz manipulator PRBT 6
=======================

This guide provides instructions on how to set up Pilz manipulators PRBT 6 using ros2_canopen.
Before following this guide, make sure to refer to the user guide to :doc:`../user-guide/configuration`,
:doc:`../user-guide/how-to-create-a-configuration` and :doc:`../user-guide/how-to-create-a-robot-system`.
Additionally, this guide is based on: `pilz_robots <https://github.com/PilzDE/pilz_robots>`_.

To configure the PRBT 6 using ros2_canopen, please refer to the pre-existing configuration in the `pilz_robot <https://github.com/ipa-cmh/prbt_robot.git>`_ package.


Package creation and setup
----------------------------
- Create a new configuration package for the robot with the name ``prbt_robot_support``.

    .. code-block:: console

        $ ros2 pkg create --dependencies ros2_canopen lely_core_libraries --build-type ament_cmake prbt_robot_support
        $ cd prbt_robot_support
        $ rm -rf src
        $ rm -rf include
        $ mkdir -p launch
        $ mkdir -p config
        $ mkdir -p urdf
        $ touch config/prbt_ros2_control.yaml

- Create a new bus configuration folder with name ``prbt``. And create ``bus.yml`` and copy ``prbt_0_1.dcf`` from `pilz_support <https://github.com/PilzDE/pilz_robots/tree/noetic-devel/prbt_support/config>`_ package.

    Now the package structure should look like this:

    ::

        prbt_robot_support
            ├── config
            │   ├── prbt
            │   |   ├── bus.yml
            │   |   └── prbt_0_1.dcf
            │   └── prbt_ros2_control.yaml
            ├── launch
            ├── urdf
            ├── CMakeLists.txt
            └── package.xml

- Add the following to the ``bus.yml``

    .. code-block:: yaml

        options:
            dcf_path: "@BUS_CONFIG_PATH@"
            master:
                node_id: 1
                driver: "ros2_canopen::MasterDriver"
                package: "canopen_master_driver"
                sync_period: 10000

            defaults:
                dcf: "prbt_0_1.dcf"
                driver: "ros2_canopen::Cia402Driver"
                package: "canopen_402_driver"
                period: 10
                heartbeat_producer: 1000
                switching_state: 2
                position_mode: 7
                scale_pos_from_dev: 0.00001745329252
                scale_pos_to_dev: 57295.7795131
                sdo:
                    - {index: 0x6081, sub_index: 0, value: 1000}
                    - {index: 0x60C2, sub_index: 1, value: 10} # Interpolation time period at 10 ms matches the period.

                tpdo: # TPDO needed statusword, actual velocity, actual position, mode of operation
                    1:
                    enabled: true
                    cob_id: "auto"
                    transmission: 0x01
                    mapping:
                        - {index: 0x6041, sub_index: 0} # status word
                        - {index: 0x6061, sub_index: 0} # mode of operation display
                    2:
                    enabled: true
                    cob_id: "auto"
                    transmission: 0x01
                    mapping:
                        - {index: 0x6064, sub_index: 0} # position actual value
                        - {index: 0x606c, sub_index: 0} # velocity actual position
                    3:
                    enabled: false
                    4:
                    enabled: false
                rpdo: # RPDO needed controlword, target position, target velocity, mode of operation
                    1:
                    enabled: true
                    cob_id: "auto"
                    mapping:
                    - {index: 0x6040, sub_index: 0} # controlword
                    - {index: 0x6060, sub_index: 0} # mode of operation
                    - {index: 0x60C1, sub_index: 1} # interpolated position data
                    2:
                    enabled: true
                    cob_id: "auto"
                    mapping:
                    - {index: 0x607A, sub_index: 0} # target position

            nodes:
                prbt_joint_1:
                    node_id: 3
                prbt_joint_2:
                    node_id: 4
                prbt_joint_3:
                    node_id: 5
                prbt_joint_4:
                    node_id: 6
                prbt_joint_5:
                    node_id: 7
                prbt_joint_6:
                    node_id: 8

- Create ``prbt.ros2_control.xacro`` file in ``urdf`` folder and add the following to the file:

    .. code-block:: xml

        <?xml version="1.0"?>
        <robot xmlns:xacro="http://www.ros.org/wiki/xacro">

            <xacro:macro name="prbt_ros2_control" params="
                name
                prefix
                bus_config
                master_config
                can_interface_name
                master_bin">

                <ros2_control name="${name}" type="system">
                    <hardware>
                        <plugin>canopen_ros2_control/RobotSystem</plugin>
                        <param name="bus_config">${bus_config}</param>
                        <param name="master_config">${master_config}</param>
                        <param name="can_interface_name">${can_interface_name}</param>
                        <param name="master_bin">"${master_bin}"</param>
                    </hardware>
                    <joint name="${prefix}joint_1">
                        <param name="device_name">prbt_joint_1</param>
                    </joint>
                    <joint name="${prefix}joint_2">
                        <param name="device_name">prbt_joint_2</param>
                    </joint>
                    <joint name="${prefix}joint_3">
                        <param name="device_name">prbt_joint_3</param>
                    </joint>
                    <joint name="${prefix}joint_4">
                        <param name="device_name">prbt_joint_4</param>
                    </joint>
                    <joint name="${prefix}joint_5">
                        <param name="device_name">prbt_joint_5</param>
                    </joint>
                    <joint name="${prefix}joint_6">
                        <param name="device_name">prbt_joint_6</param>
                    </joint>
                </ros2_control>

            </xacro:macro>

        </robot>

- Add the following to the ``prbt_ros2_control.yaml`` file:

    .. code-block:: yaml

        controller_manager:
            ros__parameters:
                update_rate: 100  # Hz

                joint_state_broadcaster:
                type: joint_state_broadcaster/JointStateBroadcaster

                arm_controller:
                type: joint_trajectory_controller/JointTrajectoryController

        arm_controller:
            ros__parameters:
                joints:
                    - prbt_joint_1
                    - prbt_joint_2
                    - prbt_joint_3
                    - prbt_joint_4
                    - prbt_joint_5
                    - prbt_joint_6
                command_interfaces:
                    - position
                state_interfaces:
                    - position
                    - velocity
                stop_trajectory_duration: 0.2
                state_publish_rate:  100.0
                action_monitor_rate: 25.0
                goal_time: 0.0
                limits:
                    prbt_joint_1:
                        has_acceleration_limits: true
                        max_acceleration: 6.0
                    prbt_joint_2:
                        has_acceleration_limits: true
                        max_acceleration: 6.0
                    prbt_joint_3:
                        has_acceleration_limits: true
                        max_acceleration: 6.0
                    prbt_joint_4:
                        has_acceleration_limits: true
                        max_acceleration: 6.0
                    prbt_joint_5:
                        has_acceleration_limits: true
                        max_acceleration: 6.0
                    prbt_joint_6:
                        has_acceleration_limits: true
                        max_acceleration: 6.0

- Create a launch file with name ``robot.launch.py`` in the launch directory of your package. Follow the instructions :doc:`../user-guide/how-to-create-a-robot-system`  to complete the launch file. The launch file should look like this:

    .. code-block:: python

        import os
        from ament_index_python import get_package_share_directory
        from launch import LaunchDescription
        from launch.actions import DeclareLaunchArgument
        from launch.substitutions import Command, FindExecutable, LaunchConfiguration, PathJoinSubstitution
        from launch_ros.actions import Node
        from launch_ros.substitutions import FindPackageShare
        from launch.actions import IncludeLaunchDescription
        from launch.launch_description_sources import PythonLaunchDescriptionSource

        from launch.actions import IncludeLaunchDescription
        from launch.launch_description_sources import PythonLaunchDescriptionSource
        import launch_ros

        def generate_launch_description():
            declared_arguments = []

            declared_arguments.append(
                DeclareLaunchArgument(
                    "description_package",
                    description="Package where urdf file is stored.",
                    default_value="prbt_robot_support"
                )
            )
            declared_arguments.append(
                DeclareLaunchArgument(
                    "can_interface_name",
                    default_value="vcan0",
                    description="Interface name for can",
                )
            )
            declared_arguments.append(
                DeclareLaunchArgument(
                    "use_ros2_control",
                    default_value="true",
                    description="Use ros2_control",
                )
            )

            controller_config = PathJoinSubstitution([FindPackageShare("prbt_robot_support"), "config", "prbt_ros2_control.yaml"])
            bus_config = PathJoinSubstitution([FindPackageShare("prbt_robot_support"), "config", "prbt", "bus.yml"])
            master_config = PathJoinSubstitution([FindPackageShare("prbt_robot_support"), "config", "prbt", "master.dcf"])
            can_interface_name = LaunchConfiguration("can_interface_name")

            master_bin_path = os.path.join(
                        get_package_share_directory("prbt_robot_support"),
                        "config",
                        "prbt",
                        "master.bin",
                    )
            if not os.path.exists(master_bin_path):
                master_bin_path = ""
            robot_description_content = Command(
                [
                    PathJoinSubstitution([FindExecutable(name="xacro")]),
                    " ",
                    PathJoinSubstitution([FindPackageShare(LaunchConfiguration("description_package")), "urdf", "prbt.xacro"]),
                    " ",
                    "bus_config:=",
                    bus_config,
                    " ",
                    "master_config:=",
                    master_config,
                    " ",
                    "master_bin:=",
                    master_bin_path,
                    " ",
                    "can_interface_name:=",
                    can_interface_name,
                ]
            )
            robot_description = {"robot_description": launch_ros.descriptions.ParameterValue(robot_description_content, value_type=str)}

            robot_state_publisher_node = Node(
                package="robot_state_publisher",
                executable="robot_state_publisher",
                output="both",
                parameters=[robot_description],
            )

            # Controller manager
            controller_manager_node = Node(
                package="controller_manager",
                executable="ros2_control_node",
                output="both",
                parameters=[robot_description, controller_config],
            )

            joint_state_broadcaster_spawner = Node(
                package="controller_manager",
                executable="spawner",
                arguments=["joint_state_broadcaster", "--controller-manager", "/controller_manager"],
            )
            arm_controller_spawner = Node(
                package="controller_manager",
                executable="spawner",
                arguments=["arm_controller", "--controller-manager", "/controller_manager"],
            )

            nodes_list = [
                robot_state_publisher_node,
                controller_manager_node,
                joint_state_broadcaster_spawner,
                arm_controller_spawner,
            ]

            return LaunchDescription(declared_arguments + nodes_list)

- Edit the CMakeLists.txt file of your package and add the following lines after the find_package section.

    .. code-block:: cmake

        cogen_dcf(prbt)

        install(DIRECTORY
        launch urdf meshes
        DESTINATION share/${PROJECT_NAME})

        install(FILES config/prbt_ros2_control.yaml
        DESTINATION share/${PROJECT_NAME}/config)

- Build your package and source the setup file.

MoveIt2 setup
-------------

Follow the `MoveIt Setup Assistance <https://moveit.picknik.ai/main/doc/examples/setup_assistant/setup_assistant_tutorial.html?highlight=setup%20assistance>`_ tutorial
and create the MoveIt2 package for your robot. The MoveIt2 package should be created in the same workspace as your robot package.

- Update ``moveit_controller.yaml`` file in the config directory of your MoveIt2 package. The file should look like this:

    .. code-block:: yaml

        # MoveIt uses this configuration for controller management
        trajectory_execution:
        allowed_execution_duration_scaling: 1.2
        allowed_goal_duration_margin: 0.5
        allowed_start_tolerance: 0.01

        moveit_controller_manager: moveit_simple_controller_manager/MoveItSimpleControllerManager

        moveit_simple_controller_manager:
        controller_names:
            - arm_controller

        arm_controller:
            type: FollowJointTrajectory
            action_ns: follow_joint_trajectory
            default: True
            joints:
            - prbt_joint_1
            - prbt_joint_2
            - prbt_joint_3
            - prbt_joint_4
            - prbt_joint_5
            - prbt_joint_6

- Create a launch file ``moveit_planning_execution.launch.py`` to launch moveit and robot components.

    .. code-block:: python

        from launch import LaunchDescription
        from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription
        from launch.substitutions import LaunchConfiguration, PathJoinSubstitution
        from launch_ros.substitutions import FindPackageShare
        from launch.actions import IncludeLaunchDescription
        from launch.launch_description_sources import PythonLaunchDescriptionSource

        from launch.actions import TimerAction

        from moveit_configs_utils import MoveItConfigsBuilder


        def generate_launch_description():
            moveit_config = MoveItConfigsBuilder(
                "prbt", package_name="prbt_robot_moveit_config"
            ).to_moveit_configs()
            declared_arguments = []

            declared_arguments.append(
                DeclareLaunchArgument(
                    "can_interface_name",
                    default_value="can0",
                    description="Interface name for can",
                )
            )

            robot_hw_node = IncludeLaunchDescription(
                PythonLaunchDescriptionSource(
                    [PathJoinSubstitution([FindPackageShare("prbt_robot_support"), "launch", "robot.launch.py"])],
                ),
                launch_arguments={
                    "can_interface_name": LaunchConfiguration("can_interface_name"),
                }.items(),
            )

            virtual_joints = IncludeLaunchDescription(
                PythonLaunchDescriptionSource(
                    str(
                        moveit_config.package_path / "launch/static_virtual_joint_tfs.launch.py"
                    )
                ),
            )

            move_group = IncludeLaunchDescription(
                PythonLaunchDescriptionSource(
                    str(moveit_config.package_path / "launch/move_group.launch.py")
                ),
            )

            rviz = IncludeLaunchDescription(
                PythonLaunchDescriptionSource(
                    str(moveit_config.package_path / "launch/moveit_rviz.launch.py")
                ),
            )


            node_list = [
                robot_hw_node,
                virtual_joints,
                move_group,
                rviz,
            ]

            return LaunchDescription(declared_arguments + node_list)

Running the PRBT robot
------------------------
There are two ways to run the demo. First you can use ``canopen_fake_slave`` to simulate the robot using CAN interface ``vcan0``. Second you can use the real robot.
Refer :doc:`../quickstart/operation` to configure CAN interface.

.. code-block:: bash

    # Run the demo using fake robot
    ros2 launch prbt_robot_moveit_config moveit_planning_execution.launch.py can_interface_name:=vcan0

    # Run the demo using real robot
    ros2 launch prbt_robot_moveit_config moveit_planning_execution.launch.py can_interface_name:=can0

Rviz2:

.. image:: ../images/prbt_rviz2.png
    :width: 90%
    :align: center


================================================
FILE: canopen/sphinx/application/trinamic.rst
================================================
Trinamic Stepper Motor control
==============================

Introduction
------------

This tutorial is a simple example of how to use the ros2_canopen package to control a `Trinamic smart stepper motor <https://www.trinamic.com/products/drives/details/pd42-x-1270/>`_.

Getting started
---------------

If you haven't already done so, follow the steps in the :doc:`../user-guide/configuration`.

Configuration
-------------

- Create a new folder in the ``config`` folder of your configuration package. Name it ``single-pd42``.
- Download ``.eds`` file from `Trinamic <https://www.trinamic.com/fileadmin/assets/Products/Drives_Software/TMCM-1270_CANopen_V326.zip>`_ and place ``TMCM-1270.eds`` in the ``single-pd42`` folder.
- Create a ``bus.yml`` file in the ``single-pd42`` folder with the following content:

    .. code-block:: yaml

        options:
            dcf_path: "@BUS_CONFIG_PATH@"

        master:
            node_id: 2
            driver: "ros2_canopen::MasterDriver"
            package: "canopen_master_driver"
            sync_period: 20000


        defaults:
            dcf: "TMCM-1270.eds"
            driver: "ros2_canopen::Cia402Driver"
            package: "canopen_402_driver"
            polling: false
            heartbeat_producer: 1000 # Heartbeat every 1000 ms
            sdo: # SDO executed during config
                - {index: 0x6081, sub_index: 0, value: 500000} # Set velocity
                - {index: 0x6083, sub_index: 0, value: 1000000} # Set acceleration
                - {index: 0x6083, sub_index: 0, value: 1000000} # Set deceleration
                - {index: 0x6085, sub_index: 0, value: 1000000} # Set quickstop deceleration
                - {index: 0x6098, sub_index: 0, value: 35} # Set default homing mode to 35
                - {index: 0x60C2, sub_index: 1, value: 50} # Set interpolation time for cyclic modes to 50 ms
                - {index: 0x60C2, sub_index: 2, value: -3} # Set base 10-3s

        nodes:
            trinamic_pd42:
                node_id: 1


- Edit the ``CMakeLists.txt`` file in the ``config`` folder of your configuration package and add the following lines:

    .. code-block:: cmake

        cmake_minimum_required(VERSION 3.8)
        project(trinamic_pd42_can)

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

        # find dependencies
        find_package(ament_cmake REQUIRED)
        find_package(rclcpp REQUIRED)
        find_package(std_srvs REQUIRED)
        find_package(canopen REQUIRED)
        find_package(lely_core_libraries REQUIRED)
        find_package(canopen_interfaces REQUIRED)

        # generate_dcf(single-pd42)
        cogen_dcf(single-pd42)

        add_executable(position_tick_client src/position_tick_motor.cpp)
        target_link_libraries(position_tick_client
            ${canopen_interfaces_TARGETS}
            ${std_srvs_TARGETS}
            rclcpp::rclcpp
        )

        install(TARGETS
        position_tick_client
        DESTINATION lib/${PROJECT_NAME})

        # install launch file
        install(DIRECTORY
        launch/
        DESTINATION share/${PROJECT_NAME}
        )

        if(BUILD_TESTING)
        find_package(ament_lint_auto REQUIRED)
        endif()

        ament_package()

- Create launch file in folder ``launch`` and add the following content:

    .. code-block:: python

        import os
        import sys

        import launch
        from launch.actions import IncludeLaunchDescription
        from launch.launch_description_sources import PythonLaunchDescriptionSource
        from ament_index_python import get_package_share_directory
        from launch import LaunchDescription


        def generate_launch_description():
            ld = LaunchDescription()
            slave_eds_path = os.path.join(
                get_package_share_directory("trinamic_pd42_can"), "config", "single-pd42", "TMCM-1270.eds"
            )

            slave_node_1 = IncludeLaunchDescription(
                PythonLaunchDescriptionSource(
                    [
                        os.path.join(get_package_share_directory("canopen_fake_slaves"), "launch"),
                        "/cia402_slave.launch.py",
                    ]
                ),
                launch_arguments={
                    "node_id": "1",
                    "node_name": "pd42_slave",
                    "slave_config": slave_eds_path,
                }.items(),
            )
            master_bin_path = os.path.join(
                get_package_share_directory("trinamic_pd42_can"),
                "config",
                "single-pd42",
                "master.bin",
            )
            if not os.path.exists(master_bin_path):
                master_bin_path = ""

            device_container = IncludeLaunchDescription(
                PythonLaunchDescriptionSource(
                    [
                        os.path.join(get_package_share_directory("canopen_core"), "launch"),
                        "/canopen.launch.py",
                    ]
                ),
                launch_arguments={
                    "master_config": os.path.join(
                        get_package_share_directory("trinamic_pd42_can"),
                        "config",
                        "single-pd42",
                        "master.dcf",
                    ),
                    "master_bin": master_bin_path,
                    "bus_config": os.path.join(
                        get_package_share_directory("trinamic_pd42_can"),
                        "config",
                        "single-pd42",
                        "bus.yml",
                    ),
                    "can_interface_name": "vcan0",
                }.items(),
            )

            ld.add_action(device_container)
            ld.add_action(slave_node_1)

            return ld

Running the example
-------------------

To begin, follow the instructions for :doc:`../quickstart/operation`, which can be done using either a virtual or peak CAN interface.

If you prefer to use a real CAN interface, you will need to modify the launch file by changing the ``can_interface_name`` argument to ``can0``.
Additionally, if you are using real hardware, you should comment out the fake slave launch by adding a *#* in front of the line *ld.add_action(slave_node_1)*.
Once these changes have been made, you can launch the example.

.. code-block:: console

    ros2 launch trinamic_pd42_can <your launch file>.launch.py

Initilaize the motor by calling the service ``/trinamic_pd42/init``:

.. code-block:: console

    ros2 service call /trinamic_pd42/init std_srvs/srv/Trigger

Set the operation mode to ``Profile Position Mode`` by calling the service ``/trinamic_pd42/position_mode``:

.. code-block:: console

    ros2 service call /trinamic_pd42/position_mode std_srvs/srv/Trigger

Set the target to the motor by calling the service ``/trinamic_pd42/target``:

.. code-block:: console

    ros2 service call /trinamic_pd42/target canopen_interfaces/srv/COTargetDouble "{ target: 10.0 }"

Reference
---------
You can find the source code for this example in the `trinamic_pd42_can <https://github.com/ipa-cmh/trinamic_pd42_can.git>`_ package.


================================================
FILE: canopen/sphinx/conf.py
================================================
# Copyright 2023 ROS-Industrial
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html

# -- Path setup --------------------------------------------------------------

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
from pathlib import Path

# -- Project information -----------------------------------------------------

project = "ros2_canopen"
copyright = "2022, Christoph Hellmann Santos,  Harshavardhan Deshpande"
author = "Christoph Hellmann Santos,  Harshavardhan Deshpande"

# The full version, including alpha/beta/rc tags
release = "0.0.1"


# -- General configuration ---------------------------------------------------

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
    "sphinx_rtd_theme",
    "sphinx_mdinclude",
    "sphinx.ext.imgmath",
    "sphinx.ext.todo",
    "sphinx.ext.graphviz",
    "sphinxcontrib.plantuml",
    "breathe",
]

breathe_default_project = "ros2_canopen"


def get_package(package: str):
    path = Path(__file__).parent.parent.parent.joinpath(f"{package}/include/{package}")
    files_gen = path.glob("*.hpp")
    files = []
    for file in files_gen:
        files.append(file.name)
    return (path, files)


breathe_projects = {
    "ros2_canopen": "../doxygen/_build/xml/",
}


# Tell sphinx what the primary language being documented is.
primary_domain = "cpp"

# Tell sphinx what the pygments highlight language should be.
highlight_language = "cpp"


# Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"]

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]


# -- Options for HTML output -------------------------------------------------

# The theme to use for HTML and HTML Help pages.  See the documentation for
# a list of builtin themes.
#
html_theme = "sphinx_rtd_theme"

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ["_static"]
html_logo = "images/ros2-canopen-logo.png"
html_css_files = ["css/custom.css"]
pygments_style = "sphinx"


================================================
FILE: canopen/sphinx/developers-guide/architecture.rst
================================================
Architecture
=============

The architecture of the ROS2 CANopen stack is based on the composition
concept of ROS2. In ROS2 components are dynamically loadable ROS2 nodes
which are loaded by a component manager.

Device Container
""""""""""""""""""
The core of the ROS2 CANopen stack is the ros2_canopen::DeviceContainer which implements
the rclcpp::ComponentManager class. The DeviceContainer enables loading drivers for the
CANopen master and the devices on the bus, that have been exported as rclcpp_components.
CANopen Master drivers need to implement the ros2_canopen::CanopenMasterInterface, CANopen
Device drivers need to implement the ros2_canopen::CanopenDriverInterface.

The difference between the ros2_canopen::DeviceContainer and the rclcpp::ComponentContainer
is that the device container loads only master and driver components specified in the bus
configuration (bus.yml). It does not have services for loading components online. All components
that are connected or will be connected to the CANopen Bus need to be known and specified in
the bus.yml before starting the device container.

.. uml::

  rclcpp::ComponentManager <|-- ros2_canopen::DeviceContainer

  class rclcpp::ComponentManager
  {
    std::weak_ptr<rclcpp::Executor> executor_
    std::vector<ComponentResource> get_component_resources(std::string package_name)
    std::shared_ptr<NodeFactory> create_component_factory(ComponentResource resource)
    void on_list_nodes(...)
    virtual void set_executor(const std::weak_ptr<rclcpp::Executor> executor)
  }


  class ros2_canopen::DeviceContainer
  {
    std::shared_ptr<CanopenMasterInterface> can_master_
    std::shared_ptr<LifecycleManager> lifecycle_manager_
    std::map<uint16_t, std::shared_ptr<CanopenDriverInterface>> drivers_
    void on_list_nodes(...) override
    virtual void set_executor(const std::weak_ptr<rclcpp::Executor> executor) override
  }

The device container will first load the master specified in the bus configuration. Then
it will load the drivers specified in the bus configuration. If the master and drivers
specified in the bus configuration are managed nodes it will as well load the ros2_canopen::LifecycleManager.


CANopen Master Driver Architecture
"""""""""""""""""""""""""""""""""""

The architecture for CANopen master drivers looks as depicted in the class diagram. All master drivers
consist of three main classes.

The first class is the functionality class that contains the drivers functionailities independently of
the ROS2 node type. This class needs to implement the ros2_canopen::node_interfaces::NodeCanopenMasterInterface.
ros2_canopen::node_interfaces::NodeCanopenMaster is an abstract class that provides some useful functionality and
implements the ros2_canopen::node_interfaces::NodeCanopenMasterInterface. Usually, master drivers will inherit from
ros2_canopen::node_interfaces::NodeCanopenMaster.

The second class is the class that wraps the functionality class in a rclcpp::Node. This class should implement the
ros2_canopen::CanopenMasterInterface. The canopen_core package provides a convenience class ros2_canopen::CanopenMaster
that should be inherited from and implements the ros2_canopen::CanopenMasterInterface.

The third class is the class that wraps the functionality class in a rclcpp_lifecycle::LifecycleNode. This class should implement the
ros2_canopen::CanopenMasterInterface. The canopen_core package provides a convenience class ros2_canopen::LifecycleCanopenMaster
that should be inherited from and implements the ros2_canopen::CanopenMasterInterface.

.. uml::


  package "canopen_core" {
    interface ros2_canopen::CanopenMasterInterface
    interface ros2_canopen::node_interfaces::NodeCanopenMasterInterface
    abstract ros2_canopen::LifecycleCanopenMaster
    abstract ros2_canopen::node_interfaces::NodeCanopenMaster
    abstract ros2_canopen::CanopenMaster


    ros2_canopen::node_interfaces::NodeCanopenMasterInterface - ros2_canopen::CanopenMaster : < has
    ros2_canopen::LifecycleCanopenMaster - ros2_canopen::node_interfaces::NodeCanopenMasterInterface : > has

    ros2_canopen::CanopenMasterInterface <|-- ros2_canopen::LifecycleCanopenMaster
    ros2_canopen::node_interfaces::NodeCanopenMasterInterface <|-- ros2_canopen::node_interfaces::NodeCanopenMaster
    ros2_canopen::CanopenMasterInterface <|-- ros2_canopen::CanopenMaster

  }

  package "canopen_master_driver" {

    class ros2_canopen::LifecycleMasterDriver << (C, blue) Component>>
    class ros2_canopen::node_interfaces::NodeCanopenBasicMaster
    class ros2_canopen::MasterDriver << (C, blue) Component>>
    ros2_canopen::LifecycleMasterDriver - ros2_canopen::node_interfaces::NodeCanopenBasicMaster: > has
    ros2_canopen::node_interfaces::NodeCanopenBasicMaster - ros2_canopen::MasterDriver : < has
    ros2_canopen::LifecycleCanopenMaster <|-- ros2_canopen::LifecycleMasterDriver
    ros2_canopen::node_interfaces::NodeCanopenMaster <|-- ros2_canopen::node_interfaces::NodeCanopenBasicMaster
    ros2_canopen::CanopenMaster <|-- ros2_canopen::MasterDriver
  }


CANopen Device Driver Architecture
"""""""""""""""""""""""""""""""""""

The architecture for CANopen device drivers looks as depicted in the class diagram. All device drivers
consist of three main classes.

The first class is the functionality class that contains the drivers functionailities independently of
the ROS2 node type. This class needs to implement the ros2_canopen::node_interfaces::NodeCanopenDriverInterface.
ros2_canopen::node_interfaces::NodeCanopenDriver is an abstract class that provides some useful functionality and
implements the ros2_canopen::node_interfaces::NodeCanopenDriverInterface. If you plan to write a driver from scratch
based on Lely Core library, your functionality class should inherit from ros2_canopen::node_interfaces::NodeCanopenDriver.
If you want to use the existing lely_driver_bridge, your functionality class should inherit from ros2_canopen::NodeCanopenBaseDriver.

The second class is the class that wraps the functionality class in a rclcpp::Node. This class should implement the
ros2_canopen::CanopenDriverInterface. The canopen_core package provides a convenience class ros2_canopen::CanopenDriver
that should be inherited from and implements the ros2_canopen::CanopenDriverInterface.

The third class is the class that wraps the functionality class in a rclcpp_lifecycle::LifecycleNode. This class should implement the
ros2_canopen::CanopenDriverInterface. The canopen_core package provides a convenience class ros2_canopen::LifecycleCanopenDriver
that should be inherited from and implements the ros2_canopen::CanopenDriverInterface.

.. uml::

  package "canopen_core" {
    interface ros2_canopen::CanopenDriverInterface
    interface ros2_canopen::node_interfaces::NodeCanopenDriverInterface
    abstract ros2_canopen::LifecycleCanopenDriver
    abstract ros2_canopen::node_interfaces::NodeCanopenDriver
    abstract ros2_canopen::CanopenDriver


    ros2_canopen::node_interfaces::NodeCanopenDriverInterface - ros2_canopen::CanopenDriver : < has
    ros2_canopen::LifecycleCanopenDriver - ros2_canopen::node_interfaces::NodeCanopenDriverInterface : > has

    ros2_canopen::CanopenDriverInterface <|-- ros2_canopen::LifecycleCanopenDriver
    ros2_canopen::node_interfaces::NodeCanopenDriverInterface <|-- ros2_canopen::node_interfaces::NodeCanopenDriver
    ros2_canopen::CanopenDriverInterface <|-- ros2_canopen::CanopenDriver

  }


  package "canopen_base_driver" {

    class ros2_canopen::LifecycleBaseDriver << (C, blue) Component>>
    class ros2_canopen::node_interfaces::NodeCanopenBaseDriver
    class ros2_canopen::BaseDriver << (C, blue) Component>>
    ros2_canopen::LifecycleBaseDriver - ros2_canopen::node_interfaces::NodeCanopenBaseDriver: > has
    ros2_canopen::node_interfaces::NodeCanopenBaseDriver - ros2_canopen::BaseDriver : < has
    ros2_canopen::LifecycleCanopenDriver <|-- ros2_canopen::LifecycleBaseDriver
    ros2_canopen::node_interfaces::NodeCanopenDriver <|-- ros2_canopen::node_interfaces::NodeCanopenBaseDriver
    ros2_canopen::CanopenDriver <|-- ros2_canopen::BaseDriver
  }

  package "canopen_proxy_driver" {
    class ros2_canopen::LifecycleProxyDriver << (C, blue) Component>>
    class ros2_canopen::node_interfaces::NodeCanopenProxyDriver
    class ros2_canopen::ProxyDriver << (C, blue) Component>>
    ros2_canopen::LifecycleProxyDriver - ros2_canopen::node_interfaces::NodeCanopenProxyDriver: > has
    ros2_canopen::node_interfaces::NodeCanopenProxyDriver - ros2_canopen::ProxyDriver : < has
    ros2_canopen::LifecycleCanopenDriver <|-- ros2_canopen::LifecycleProxyDriver
    ros2_canopen::node_interfaces::NodeCanopenBaseDriver <|-- ros2_canopen::node_interfaces::NodeCanopenProxyDriver
    ros2_canopen::CanopenDriver <|-- ros2_canopen::ProxyDriver
  }

  package "canopen_402_driver" {
    class ros2_canopen::LifecycleCia402Driver << (C, blue) Component>>
    class ros2_canopen::node_interfaces::NodeCanopen402Driver
    class ros2_canopen::Cia402Driver << (C, blue) Component>>
    ros2_canopen::LifecycleCia402Driver - ros2_canopen::node_interfaces::NodeCanopen402Driver: > has
    ros2_canopen::node_interfaces::NodeCanopen402Driver - ros2_canopen::Cia402Driver : < has
    ros2_canopen::LifecycleCanopenDriver <|-- ros2_canopen::LifecycleCia402Driver
    ros2_canopen::node_interfaces::NodeCanopenProxyDriver <|-- ros2_canopen::node_interfaces::NodeCanopen402Driver
    ros2_canopen::CanopenDriver <|-- ros2_canopen::Cia402Driver
  }


================================================
FILE: canopen/sphinx/developers-guide/design-objectives.rst
================================================
Design Objectives
======================

The ros_canopen stack had a number of drawbacks especially when it came
to maintainablity and complexity. In order to address these drawbacks, we
have decided to redesign the ros2_canopen stack completely with the following
development goals.


.. csv-table:: Development Objectives
  :header-rows: 1
  :class: longtable
  :delim: ;
  :widths: 1 2

  Objective; Description
  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.
  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.
  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.
  Enable controlling drives via ros2_control; A driver for CIA402 and a ros2_control interface need to be developed.
  Enable controlling drives via ros2 ervice interface; A driver for CIA402 and a service interface need to be developed.
  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.
  Good enough documentation; Write documentation for using and understanding the ros2_canopen stack.


================================================
FILE: canopen/sphinx/developers-guide/new-device-manager.rst
================================================
Creating your device manager
============================


================================================
FILE: canopen/sphinx/developers-guide/new-driver.rst
================================================
Creating a new device driver
============================

Creating your own device driver is fairly easy in ros2_canopen. You should do this if you
need to create a driver for a specific device or a specific device profile that is not yet supported. If you create
a driver for a device profile we are happy to integrate the package into this repository - simply create
a PR.

What you need to do
""""""""""""""""""""
To create a new driver you need to implement at least two classes. One being the functional class,
that contains your drivers functionalities. The other being a ROS2 wrapper node. Generally we recommend
creating one ROS2 wrapper node and another ROS2 lifecycle wrapper node.

How you do it
""""""""""""""
First you need to decide from which extension point you want to start. Usually, this is either the core interface, the base driver
or the proxy driver. Base driver provides you with all necessary callbacks for CANopen functionalities but does
not come with any ROS2 interface. Proxy driver has a simple forwarding ROS2 interface that is useful for any driver.
The core interface comes without any functionality, you need to implement everything on your own.
We recommend creating you driver based on Proxy driver, this will be explained here.

Create the package
------------------
Create your new package using the standard ros2 pkg commands. Make sure you add the following dependencies:

* rclcpp
* rclcpp_components
* rclcpp_lifecycle
* lifecycle_msgs
* canopen_core
* canopen_interfaces
* canopen_base_driver
* canopen_proxy_driver
* lely_core_libraries
* std_msgs
* std_srvs

Once done add a subfolder ``node_interfaces`` in the ``src/`` and the ``include/[pacakge_name]/`` folders.


Create the functionality class
------------------------------
The functionality class is structured similar to a LifecycleNode. The functionality class
has the following callback functions that are related to lifecycle which you can override:

* void configure(bool called_from_base)
* void activate(bool called_from_base)
* void deactivate(bool called_from_base)
* void cleanup(bool called_from_base)
* void shutdown(bool called_from_base)

CANopen functionality
*********************
In addition to the functions there are callbacks for CANopen functionality that you can
override:

* void on_rpdo(COData data)
* void on_nmt(NmtState nmt_state)

To interact with the CANopen device you can use the ros2_canopen::LelyDriverBridge object,
that is stored in the functionality class (this->driver_). The ros2_canopen::LelyDriverBridge
provides the following functions you should use in your driver:

* void nmt_command(NmtState nmt_state)
* void tpdo_transmit(COData data)
* std::future<bool>async_sdo_write(COData data)
* std::future<COData>async_sdo_read(COData data)

.. note::

   The CANopen related functionality can only be used in the activate function or timers/threads that
   were started by the activate function. If you start timers or threads in the activate function, that
   use CANopen functionality, these have to be stopped in the deactivate function.

ROS2 functionality
******************
ROS2 functionality is available via the ``node_`` object of the functionality class. This
object has a templated type and can either be a ``rclcpp::Node`` or ``rclcpp_lifecycle::LifecycleNode``.
You can use the standard functions like create_timer, create_publisher etc.

.. note::

   Currently it seems, that when you use template functions i.e. ``node_->create_publisher<xyz>(...)`` you
   need to create a template specialisation.



Your class declaration should look like this:

.. code-block:: C++
   :name: "node_interfaces/node_canopen_xxx_driver.hpp"

   node_interfaces/node_canopen_xxx_driver.hpp:

   #include <canopen_proxy_driver/node_interfaces/node_canopen_proxy_driver.hpp>

   template <class NODETYPE>
   class NodeCanopenXXXDriver : public NodeCanopenProxyDriver<NODETYPE>
   {
      static_assert(
            std::is_base_of<rclcpp::Node, NODETYPE>::value ||
               std::is_base_of<rclcpp_lifecycle::LifecycleNode, NODETYPE>::value,
            "NODETYPE must derive from rclcpp::Node or rclcpp_lifecycle::LifecycleNode");
   public:
      NodeCanopenXXXDriver(NODETYPE *node);

      /*Your overrides etc. go here*/
   };

Your member definitions go here:

.. code-block:: C++
   :name: "node_interfaces/node_canopen_xxx_driver_impl.hpp"

   node_interfaces/node_canopen_xxx_driver.hpp:

   #include node_interfaces/node_canopen_xxx_driver.hpp

   /*Your function definitions go here.*/

Your explicit template instantiations go here:

.. code-block:: C++
   :name: "node_interfaces/node_canopen_xxx_driver.cpp"

   node_interfaces/node_canopen_xxx_driver.cpp:

   #include node_interfaces/node_canopen_xxx_driver.hpp
   #include node_interfaces/node_canopen_xxx_driver_impl.hpp

   template class <ros2_canopen>::node_interfaces::NodeCanopenXXXDriver<rclcpp::Node>;
   template class <ros2_canopen>::node_interfaces::NodeCanopenXXXDriver<rclcpp_lifecycle::LifecycleNode>;


Create the ROS2 wrapper classes
-------------------------------

The ROS2 wrapper classes are fairly easy to create once you wrote the functionality
class. The wrappers simply use the functionality class to provide the functionality.
The ROS2 wrapper class should always be derived from ``ros2_canopen::CanopenDriver`` or
``ros2_canopen::LifecycleCanopenDriver`` .


The declaration should look like this:

.. code::

   lifecycle_xxx_driver.hpp:

   #include "canopen_xxx_driver/node_interfaces/node_canopen_xxx_driver.hpp"
   #include "canopen_core/driver_node.hpp"

   /**
      * @brief Lifecycle Proxy Driver
      *
      * A very basic driver without any functionality.
      *
      */
   class LifecycleXXXDriver : public ros2_canopen::LifecycleCanopenDriver
   {
      std::shared_ptr<node_interfaces::NodeCanopenXXXDriver<rclcpp_lifecycle::LifecycleNode>> node_canopen_xxx_driver_;
   public:
      LifecycleXXXDriver(rclcpp::NodeOptions node_options = rclcpp::NodeOptions());
   };

The definitions should look like this:

.. code::


   #include "canopen_xxx_driver/lifecycle_proxy_driver.hpp"

   using namespace ros2_canopen;


   LifecycleXXXDriver::LifecycleXXXDriver(rclcpp::NodeOptions node_options) : LifecycleCanopenDriver(node_options)
   {
   node_canopen_xxx_driver_ = std::make_shared<node_interfaces::NodeCanopenXXXDriver<rclcpp_lifecycle::LifecycleNode>>(this);
   node_canopen_proxy_driver_ = std::static_pointer_cast<node_interfaces::NodeCanopenProxyDriver>(node_canopen_xxx_driver_);
   node_canopen_driver_ = std::static_pointer_cast<node_interfaces::NodeCanopenDriverInterface>(node_canopen_xxx_driver_);
   }

   #include "rclcpp_components/register_node_macro.hpp"
   RCLCPP_COMPONENTS_REGISTER_NODE(ros2_canopen::LifecycleXXXDriver)


Adapt the CMakeLists.txt
************************
The CMakeLists.txt file should look like this:

.. code:: CMAKE

   cmake_minimum_required(VERSION 3.8)
   project(canopen_xxx_driver)

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

   # find dependencies
   find_package(ament_cmake REQUIRED)
   find_package(ament_cmake_ros REQUIRED)
   find_package(rclcpp REQUIRED)
   find_package(rclcpp_lifecycle REQUIRED)
   find_package(rclcpp_components REQUIRED)
   find_package(canopen_core REQUIRED)
   find_package(canopen_interfaces REQUIRED)
   find_package(canopen_base_driver REQUIRED)
   find_package(canopen_proxy_driver REQUIRED)
   find_package(std_msgs REQUIRED)
   find_package(std_srvs REQUIRED)

   # Functionality library
   add_library(node_canopen_xxx_driver
   src/node_interfaces/node_canopen_xxx_driver.cpp
   )
   target_compile_features(node_canopen_xxx_driver PUBLIC c_std_99 cxx_std_17)  # Require C99 and C++17
   target_compile_options(node_canopen_xxx_driver PUBLIC -Wl,--no-undefined)
   target_include_directories(node_canopen_xxx_driver PUBLIC
   $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
   $<INSTALL_INTERFACE:include>)

   target_link_libraries(node_canopen_xxx_driver PUBLIC
     canopen_proxy_driver::node_canopen_proxy_driver
   )

   # Lifecycle driver
   add_library(lifecycle_xxx_driver
   src/lifecycle_xxx_driver.cpp
   )
   target_compile_features(lifecycle_xxx_driver PUBLIC c_std_99 cxx_std_17)  # Require C99 and C++17
   target_compile_options(lifecycle_xxx_driver PUBLIC -Wl,--no-undefined)
   target_include_directories(lifecycle_xxx_driver PUBLIC
   $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
   $<INSTALL_INTERFACE:include>)

   target_link_libraries(lifecycle_xxx_driver PUBLIC
     canopen_core::node_canopen_driver
     node_canopen_xxx_driver
     rclcpp_components::component
     rclcpp_lifecycle::rclcpp_lifecycle
   )
   # Causes the visibility macros to use dllexport rather than dllimport,
   # which is appropriate when building the dll but not consuming it.
   target_compile_definitions(lifecycle_xxx_driver PRIVATE "CANOPEN_XXX_DRIVER_BUILDING_LIBRARY")

   rclcpp_components_register_nodes(lifecycle_xxx_driver "ros2_canopen::LifecycleXXXDriver")
   set(node_plugins "${node_plugins}ros2_canopen::LifecycleXXXDriver;$<TARGET_FILE:lifecycle_xxx_driver >\n")


   # Non lifecycle driver
   add_library(xxx_driver
   src/xxx_driver.cpp
   )
   target_compile_features(xxx_driver PUBLIC c_std_99 cxx_std_17)  # Require C99 and C++17
   target_compile_options(xxx_driver PUBLIC -Wl,--no-undefined)
   target_include_directories(xxx_driver PUBLIC
   $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
   $<INSTALL_INTERFACE:include>)

   target_link_libraries(xxx_driver PUBLIC
     canopen_core::node_canopen_driver
     node_canopen_xxx_driver
     rclcpp_components::component
   )

   # Causes the visibility macros to use dllexport rather than dllimport,
   # which is appropriate when building the dll but not consuming it.
   target_compile_definitions(xxx_driver PRIVATE "CANOPEN_XXX_DRIVER_BUILDING_LIBRARY")

   rclcpp_components_register_nodes(xxx_driver "ros2_canopen::XXXDriver")
   set(node_plugins "${node_plugins}ros2_canopen::XXXDriver;$<TARGET_FILE:xxx_driver >\n")

   install(
   DIRECTORY include/
   DESTINATION include
   )

   install(
   TARGETS lifecycle_xxx_driver xxx_driver node_canopen_xxx_driver
   EXPORT export_${PROJECT_NAME}
   ARCHIVE DESTINATION lib
   LIBRARY DESTINATION lib
   RUNTIME DESTINATION bin
   )

   if(BUILD_TESTING)
   endif()

   ament_export_include_directories(
   include
   )
   ament_export_libraries(
   lifecycle_xxx_driver
   xxx_driver
   node_canopen_xxx_driver
   )
   ament_export_targets(
   export_${PROJECT_NAME}
   )
   ament_export_dependencies(
     canopen_base_driver
     canopen_core
     canopen_interfaces
     canopen_proxy_driver
     rclcpp
     rclcpp_components
     rclcpp_lifecycle
     std_msgs
     std_srvs
   )

   ament_package()


================================================
FILE: canopen/sphinx/developers-guide/new-master.rst
================================================
Creating a new master
=====================


================================================
FILE: canopen/sphinx/developers-guide/overview.rst
================================================
Overview
========
ros2_canopen provides nodes for interfacing with CANopen devices. The library builds upon the professional and open source
lelycore canopen library as opposed to the previous ros_canopen stack.
In ros2_canopen the bus configuration is simplified through the use of
lelycore's configutaration toolchain.

ros2_canopen contains a number of packages that serve different serve different purposes.

* **canopen**:

  Meta-package for easy installation and contains overall documentation
  of the ros2_canopen stack.

* **lely_core_libraries**:

  A colcon package wrapper for the lelycore canopen library, for convenient
  installation with rosdep.

* **canopen_core**:

  Contains the core structures of the ros2_canopen stack such as the device manager
  and the master node and the driver node interface.

* **canopen_base_driver**:

  This package contains the base implementation of a ROS2 CANopen device driver. It can base
  used by other drivers for easy extension.

* **canopen_proxy_driver**:

  Contains an implementation of a proxy driver which simply forwards CANopen functionality
  for a specific device via ROS2 services and messages.

* **canopen_402_driver**:

  Contains an implementation of the CIA402 profile for motion controllers and exposes
  the profiles functionalities via ROS2 services and messages. The implementation is
  copied from ros_canopen/canopen_402 and this package is licensed accordingly under
  GNU Lesser General Public License v3.0!


================================================
FILE: canopen/sphinx/index.rst
================================================
ROS2 CANopen Stack
==================

This is the documentation of the ROS2 CANopen stack.

.. toctree::
  :maxdepth: 1
  :caption: Quickstart
  :glob:

  quickstart/installation
  quickstart/operation
  quickstart/examples

.. toctree::
  :maxdepth: 1
  :caption: User Guide
  :glob:

  user-guide/operation
  user-guide/configuration
  user-guide/master
  user-guide/proxy-driver
  user-guide/cia402-driver
  user-guide/how-to-create-a-configuration
  user-guide/how-to-create-a-cia301-system
  user-guide/how-to-create-a-robot-system


.. toctree::
  :maxdepth: 1
  :caption: Developer Guide
  :glob:

  developers-guide/design-objectives
  developers-guide/overview
  developers-guide/architecture
  developers-guide/new-driver
  developers-guide/new-master
  API Reference <https://ros-industrial.github.io/ros2_canopen/api/>

.. toctree::
  :maxdepth: 1
  :caption: Software Tests
  :glob:

  software-tests/**

.. toctree::
  :maxdepth: 1
  :caption: Application Demos
  :glob:

  application/**


================================================
FILE: canopen/sphinx/make.bat
================================================
@ECHO OFF

pushd %~dp0

REM Command file for Sphinx documentation

if "%SPHINXBUILD%" == "" (
	set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=.
set BUILDDIR=_build

if "%1" == "" goto help

%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
	echo.
	echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
	echo.installed, then set the SPHINXBUILD environment variable to point
	echo.to the full path of the 'sphinx-build' executable. Alternatively you
	echo.may add the Sphinx directory to PATH.
	echo.
	echo.If you don't have Sphinx installed, grab it from
	echo.https://www.sphinx-doc.org/
	exit /b 1
)

%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end

:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%

:end
popd


================================================
FILE: canopen/sphinx/quickstart/examples.rst
================================================
Running Examples
================

In order to tryout the library a few examples are provided in the ``canopen_tests`` directory.
You can run them if you have :ref:`started the vcan0 interface <quick-start-setup-can-controller>`.

Service Interface
---------------------

.. code-block:: bash

    ros2 launch canopen_tests cia402_setup.launch.py


Managed Service Interface
-------------------------

.. code-block:: bash

    ros2 launch canopen_tests cia402_lifecycle_setup.launch.py

ROS2 Control
------------

Proxy Setup
,,,,,,,,,,,

.. code-block:: bash

   ros2 launch canopen_tests canopen_system.launch.py


CiA402 Setup
,,,,,,,,,,,,

.. code-block:: bash

   ros2 launch canopen_tests cia402_system.launch.py


Robot Setup
,,,,,,,,,,,,

.. code-block:: bash

    ros2 launch canopen_tests robot_control_setup.launch.py


================================================
FILE: canopen/sphinx/quickstart/installation.rst
================================================
Installation
===============================
Clone ros2_canopen into your ROS2 workspace's source folder, install dependencies and
build with colcon and your done.

.. code-block:: console

   $ git clone https://github.com/ros-industrial/ros2_canopen.git
   $ cd ..
   $ rosdep install --from-paths src/ros2_canopen --ignore-src -r -y
   $ colcon build


================================================
FILE: canopen/sphinx/quickstart/operation.rst
================================================
Setup CAN Controller
====================
.. _quick-start-setup-can-controller:

**Option 1**: Virtual CANController

.. code-block:: console

  $ sudo modprobe vcan
  $ sudo ip link add dev vcan0 type vcan
  $ sudo ip link set vcan0 txqueuelen 1000
  $ sudo ip link set up vcan0

**Option 2**: Peak CANController

.. code-block:: console

  $ sudo modprobe peak_usb
  $ sudo ip link set can0 up type can bitrate 1000000
  $ sudo ip link set can0 txqueuelen 1000
  $ sudo ip link set up can0

Bitrate depends on your bus and devices capabilities.

**Option 3**: candleLight USB-CAN Adapter

.. code-block:: console

  $ sudo modprobe gs_usb
  $ sudo ip link set can0 up type can bitrate 500000
  $ sudo ip link set can0 txqueuelen 1000
  $ sudo ip link set up can0

Bitrate depends on your bus and devices capabilities.

**Option 4**: Adapt these steps to other socketcan devices


================================================
FILE: canopen/sphinx/software-tests/proxy-driver-test.rst
================================================
Lifecycle Proxy Driver Test
===========================

.. csv-table:: Testdetails
    :header: "Detail", "Information"
    :delim: ;

    Package; canopen_tests
    Test file; launch_tests/test_lifecycle_proxy_driver.py
    Description; Tests nmt, sdo and lifecycle of lifecycle proxy driver
    Prerequisites; vcan0 must be available

Proxy Driver Test
===========================

.. csv-table:: Testdetails
    :header: "Detail", "Information"
    :delim: ;

    Package; canopen_tests
    Test file; launch_tests/test_proxy_driver.py
    Description; Tests nmt, sdo and lifecycle of proxy driver
    Prerequisites; vcan0 must be available


================================================
FILE: canopen/sphinx/software-tests/ros2_control_system-test.rst
================================================
ros2_control SystemInterface test
=================================

Test details
------------

.. csv-table:: Tests
    :header: "Detail", "Information"
    :delim: ;

    Package; canopen_tests
    Test file; launch/canopen_system.launch.py
    Description; Create an exemplary ros2_control SystemInterface with CAN master and communicates to a slave node.
    Prerequisites; vcan0 must be available

To bring up vcan0:

   .. code-block:: bash

      sudo modprobe vcan
      sudo ip link add dev vcan0 type vcan
      sudo ip link set vcan0 txqueuelen 1000
      sudo ip link set up vcan0


Explanation of the test
------------------------

The test starts generic system interface and generic proxy controller for CanOpen devices.
Generic system interface enables integration of values from the CAN Bus into ros2_control framework and the controller enables you to send and receive data from the CAN bus through ros2_control to ROS2.

The next few lines show you some command to have exemplary usage of the ros2_control integration:

1. After the test is started check ``/dynamic_joint_states`` to show internal data from CAN nodes in ros2_control system.

   .. code-block:: bash

      ros2 topic echo /dynamic_joint_states


2. Open a new terminal and echo data from the topic ``/node_1_controller/rpdo``.

   .. code-block:: bash

      ros2 topic echo /node_1_controller/rpdo


3. Open a new terminal reset the state of nmt.

   .. code-block:: bash

      ros2 service call /node_1_controller/nmt_reset_node std_srvs/srv/Trigger {}

   You will expect changes in the ``/dynamic_joint_states`` topic.


4. In a new terminal publish some data to the controller to write them to the CAN bus:

   .. code-block:: bash

      ros2 topic pub --once /node_1_controller/tpdo canopen_interfaces/msg/COData "
      index: 0x4000
      subindex: 0
      data: 0x1122"

   Now watch how data in the topic ``/node_1_controller/rpdo`` are changing. There is a mirror of the data on 0x4001.
   That is, the slave node will mirror the data on 0x4001 via its tpdo and the proxy device will get the data via its rpdo.
   You should see this

   .. code-block:: bash

      index: 16385  # This is 0x4001
      subindex: 0
      data: 4386
      ---


================================================
FILE: canopen/sphinx/user-guide/cia402-driver.rst
================================================
Cia402 Driver
========================

The Cia402 Driver implements the CIA402 profile for motion controllers and enables setting
the drive status, operation mode and sending target values to the motion controller.

.. csv-table:: CIA402 Drivers
   :header: Type, Package, Name
   :widths: 30, 20, 50

   lifecycle, canopen_402_driver, ros2_canopen::LifecycleCia402Driver
   simple, canopen_402_driver, ros2_canopen::Cia402Driver

Services
--------

.. list-table::
  :widths: 30 20 50
  :header-rows: 1
  :align: left

  * - Services
    - Type
    - Description
  * - ~/nmt_reset_node
    - Trigger
    - Resets CANopen Device the Proxy Device Node manages.
  * - ~/sdo_read
    - CORead
    - Reads an SDO object from the specified index, subindex and datatype of the remote device.
  * - ~/sdo_write
    - COWrite
    - Writes data to an SDO object on the specified index, subindex and datatype of the remote device.
  * - ~/init
    - Trigger
    - Initialises motion controller including referencing
  * - ~/recover
    - Trigger
    - Recovers motion controller
  * - ~/halt
    - Trigger
    - Stops motion controller
  * - ~/position_mode
    - Trigger
    - Switches to profiled position mode
  * - ~/velocity_mode
    - Trigger
    - Switches to profiled velocity mode
  * - ~/torque_mode
    - Trigger
    - Switches to profiled torque mode
  * - ~/cyclic_position_mode
    - Trigger
    - Switches to cyclic position mode
  * - ~/cyclic_velocity_mode
    - Trigger
    - Switches to cyclic velocity mode
  * - ~/cyclic_torque_mode
    - Trigger
    - Switches to cyclic torque mode
  * - ~/interpolated_position_mode
    - Trigger
    - Switches to interpolated position mode, only linear mode with fixed time is supported
  * - ~/target
    - CODouble
    - Sets the target value. Only accepted when an operation mode is set.

Publishers
----------
.. list-table::
  :widths: 30 20 50
  :header-rows: 1
  :align: left

  * - Publishers
    - Type
    - Description
  * - ~/joint_states
    - sensor_msgs/msg/JointState
    - Joint states of the drive
  * - ~/nmt_state
    - String
    - Publishes NMT state on change
  * - ~/rpdo
    - COData
    - Publishes received PDO objects on reception


Subscribers
-----------

.. list-table::
  :widths: 30 20 50
  :header-rows: 1

  * - Topic
    - Type
    - Description
  * - ~/target
    - COTargetDouble
    - Sets target value.
  * - ~/tpdo
    - COData
    - Writes received data to remote device if the specified object is RPDO mapped on remote device.

Bus Configuration Parameters
----------------------------
Additional parameters that can be used in bus.yml for this driver.


.. list-table::
  :widths: 30 20 50
  :header-rows: 1

  * - Parameter
    - Type
    - Description
  * - polling
    - bool
    - Enables polling of the drive status. Default: true. If false, period will be used to run a ros2 timer as update loop. If true, the update loop will be triggered by the sync signal and directly executed in the canopen realtime loop. This requires all data processed in the update loop to be PDO, otherwise the loop will get stuck. This can speed reduce processor load significantly though.
  * - period
    - Milliseconds
    - Refresh period for 402 state machine. Should be similar to sync period of master.
  * - switching_state
    - see below
    - The state to switch the operation mode in.
  * - scale_pos_to_dev
    - double
    - Scaling factor to convert from SI units to device units for position.
  * - offset_pos_to_dev
    - double
    - Offset in device units added to scaled position commands sent to the device.
  * - scale_vel_to_dev
    - double
    - Scaling factor to convert from SI units to device units for velocity.
  * - scale_pos_from_dev
    - double
    - Scaling factor to convert from device units to SI units for position.
  * - offset_pos_from_dev
    - double
    - Offset in SI units to added to scaled position reports from the device.
  * - scale_vel_from_dev
    - double
    - Scaling factor to convert from device units to SI units for velocity.
  * - position_mode
    - int
    - The drives operation mode to use for the position interface
  * - velocity_mode
    - int
    - The drives operation mode to use for the velocity interface
  * - torque_mode
    - int
    - The drives operation mode to use for the torque interface


================================================
FILE: canopen/sphinx/user-guide/configuration.rst
================================================
Configuration Package
=====================

A configuration package contains one or more configurations for the CANopen
stack. The configuration package needs to hold the EDS/DCF files for each device,
the bus configuration and the launch files for the different configurations.

Consequently, the structure of the configuration package should look as follows:

    ::

          {package_name}
          ├── config
          │   ├── {bus_config_name_1}
          │   |   ├── bus.yml
          │   |   ├── {device1}.eds
          │   |   ├── {device...}.eds
          │   |   └── {slave_n}.eds
          │   └── {bus_config_name_2}
          │       ├── bus.yml
          │       ├── {device1}.eds
          │       ├── {device...}.eds
          │       └── {slave_n}.eds
          ├── launch
          │   ├── {bus_config_name_1}.launch.py
          |   └── {bus_config_name_1}.launch.py
          ├── CMakeLists.txt
          └── package.xml



Bus Configuration File
============================

The ros2_canopen stack relies on a YAML configuration file that is used
for configuring the bus topology and specifying configurations for
each device. The file details which devices connected to the bus, which
EDS/DCF file applies to them, which parameters of the EDS/DCF files should be
overwritten and which drivers should be used to control the devices.

Structure
---------

The YAML configuration file has the following sections:

.. code-block:: yaml

  options: # General options especially dcf_path
    [configuration item]: [value]

  master: # The configuration of the master
    [configuration item]: [value]
    [...]

  defaults: # Defaults that apply to all slave nodes
    [configuration item]: [value]
    []

  nodes: # Configurations for all slave nodes
    - [device_name]:
        [configuration item]: [value]
        [...]


Options Section
---------------
The options section holds general options. Right now these are only the following.

.. csv-table:: Options Configuration
  :header-rows: 1
  :class: longtable
  :delim: ;
  :widths: 1 1

  configuration item; description
  dcf_path;	The directory in which the generated .bin file will be available at runtime. You can set this to "@BUS_CONFIG_PATH@" and it will be auto-generated by cmake.


Master Section
--------------
The master section has a number of configuration options. These are not unique to ros2_canopen
but come from the lely core library. Below you find a list of possible configuration items.

.. csv-table:: Master Configuration
  :header-rows: 1
  :class: longtable
  :delim: ;
  :widths: 1 1

  configuration item; description
  node_id; The node-ID (default: 255)
  driver; The fully qualified class name of the master to use.
  package; The ros2 package name in which the master class can be found.
  namespace; The namespace in which the master will be created (default: "/").
  baudrate; The baudrate in kbit/s (default: 1000)
  vendor_id;The vendor-ID (default: 0x00000000)
  product_code;The product code (default: 0x00000000)
  revision_number;	 The revision number (default: 0x00000000).
  serial_number; 	The serial number (default: 0x00000000).
  heartbeat_multiplier;	The multiplication factor used to obtain the slave heartbeat consumer time from the master heartbeat producer time (default: see options section).
  heartbeat_consumer;	Specifies whether the master should monitor the heartbeats of the slaves (default: true).
  heartbeat_producer;	The heartbeat producer time in ms (default: 0).
  emcy_inhibit_time;	The EMCY inhibit time in multiples of 100 μs (default: 0, see object 1015).
  sync_period;	The SYNC interval in μs (default: 0).
  sync_window;	The SYNC window length in μs (default: 0, see object 1007).
  sync_overflow;	The SYNC counter overflow value (default: 0, see object 1019).
  error_behavior;	A dictionary of error behaviors for different classes or errors (default: {1: 0x00}, see object 1029).
  nmt_inhibit_time;	The NMT inhibit time in multiples of 100 μs (default: 0, see object 102A).
  start;	Specifies whether the master shall switch into the NMT operational state by itself (default: true, see bit 2 in object 1F80).
  start_nodes;	Specifies whether the master shall start the slaves (default: true, see bit 3 in object 1F80).
  start_all_nodes;	Specifies whether the master shall start all nodes simultaneously (default: false, see bit 1 in object 1F80).
  reset_all_nodes;	Specifies whether all slaves shall be reset in case of an error event on a mandatory slave (default: false, see bit 4 in object 1F80).
  stop_all_nodes;	Specifies whether all slaves shall be stopped in case of an error event on a mandatory slave (default: false, see bit 6 in object 1F80).
  boot_time;	The timeout for booting mandatory slaves in ms (default: 0, see object 1F89).
  boot_timeout;	The timeout for booting all slaves in ms (default: 2000ms).

Device Section
--------------
The device configuration enables configuring the characteristics of the connected CANopen
device.

.. note::
  It is important to note, that you choose the operation (simple nodes or managed nodes) by choosing
  either only lifecycle drivers or only simple drivers.

  **Mixing them will not work!**

.. csv-table:: Device Configuration
  :header-rows: 1
  :class: longtable
  :delim: ;
  :widths: 1 1

  configuration item; description
  driver; The fully qualified class name of the driver to use.
  package; The ros2 package name in which the driver class can be found.
  namespace; The namespace in which the driver will be created (default: "/").
  enable_lazy_load; A flag that states whether the driver is loaded on start-up.
  dcf;	The filename of the EDS/DCF describing the slave (mandatory).
  dcf_path;	The directory in which the generated .bin file will be available at runtime (default: see options section).
  node_id;	The node-ID (default: 255, can be omitted if specified in the DCF).
  revision_number;	The revision number (default: 0x00000000, can be omitted if specified in the DCF).
  serial_number;	The serial number (default: 0x00000000, can be omitted if specified in the DCF).
  heartbeat_multiplier;	The multiplication factor used to obtain master heartbeat consumer time from the slave heartbeat producer time (default: see options section).
  heartbeat_consumer;	Specifies whether the slave should monitor the heartbeat of the master (default: false).
  heartbeat_producer;	The heartbeat producer time in ms (default: 0).
  error_behavior;	A dictionary of error behaviors for different classes or errors (default: {}, see object 1029).
  rpdo;	The Receive-PDO configuration (see below).
  tpdo;	The Transmit-PDO configuration (see below).
  boot;	Specifies whether the slave will be configured and booted by the master (default: true, see bit 2 in object 1F81).
  mandatory;	Specifies whether the slave is mandatory (default: false, see bit 3 in object 1F81).
  reset_communication;	Specifies whether the NMT reset communication command may be sent to the slave (default: true, see bit 4 in object 1F81).
  software_file;	The name of the file containing the firmware (default: "", see object 1F58).
  software_version;	The expected software version (default: 0x00000000, see object 1F55).
  configuration_file;	The name of the file containing the configuration (default: "<dcf_path>/<name>.bin" (where <name> is the section name), see object 1F22).
  restore_configuration;	The sub-index of object 1011 to be used when restoring the configuration (default: 0x00).
  sdo_timeout_ms; The timeout to use for SDO reads/writes to this device. (default: 20ms)
  sdo;	Additional SDO requests to be sent during configuration (see below).


Further references
------------------
The dcfgen documentation gives more details on the usage of the dcfgen tool for generating DCF: https://opensource.lely.com/canopen/docs/dcf-tools/

Variables
---------

``@BUS_CONFIG_PATH@:`` Automatic config path definition if configuration package structure is followed.




Configuration Package CMake
===========================

In order to build the configuration package and generate the necessary runtime artifacts from the
bus configuration file and eds/dcf files, the lely_core_libraries package contains an extra
CMAKE macro.

**cogen_dcf(target)**

Target: the name of the configuration (e.g. for config/{bus_config_name_1} is bus_config_name_1)

.. code-block::

  cogen_dcf(bus_config)


================================================
FILE: canopen/sphinx/user-guide/how-to-create-a-cia301-system.rst
================================================
How to create a cia301 system with ros2_control
=================================================

The CiA 301 profile, also known as the CANopen application layer,
is the foundation of the CANopen protocol. It defines the basic principles,
communication services, and object dictionary used for device communication
and network management in a CANopen system.

The CiA 301 profile defines several communication services that allow devices
to exchange data and perform actions. These services include
the SDO (Service Data Object) service for transferring object data between devices,
the PDO (Process Data Object) service for real-time data exchange,
and the NMT (Network Management) service for network initialization,
device state control, and error handling.

To bring up the CiA301 interface using ROS2, it includes three steps:

- preparing the configuration for bus and ``ros2_control``
- preparing the state and command interfaces,
- and finally preparing the launch file.


Preparing the configuration
--------------------------------------------------------
To use the control system interface for CiA301 profile, we should prepare the following

- bus_conf
- master_dcf
- master_bin
- can_interface, (default: vcan0)

Define the bus configuration parameters

.. code-block:: yaml

    master:
        node_id: 1
        driver: "ros2_canopen::MasterDriver"
        package: "canopen_master_driver"
        baudrate: 250
    options:
        dcf_path: "@BUS_CONFIG_PATH@"
    joint_1:
        node_id: 0x00
        dcf: "joint.eds"
        driver: "ros2_canopen::ProxyDriver"
        package: "canopen_proxy_driver"
        reset_communication: false
    joint_2:
        node_id: 0x01
        dcf: "joint.eds"
        driver: "ros2_canopen::ProxyDriver"
        package: "canopen_proxy_driver"
        reset_communication: false

Define the ``ros2_control`` parameters

.. code-block:: yaml

    controller_manager:
        ros__parameters:
            update_rate: 100  # Hz

            joint_state_broadcaster:
                type: joint_state_broadcaster/JointStateBroadcaster

            joint_1_controller:
                type: canopen_ros2_controllers/CanopenProxyController

            joint_2_controller:
                type: canopen_ros2_controllers/CanopenProxyController

        joint_1_controller:
            ros__parameters:
                joint: joint_1


       joint_2_controller:
            ros__parameters:
                joint: joint_2

The example of master_dcf see https://github.com/ros-industrial/ros2_canopen/blob/master/canopen_tests/config/simple/simple.eds


Use RPDO to access the current state
--------------------------------------------------------
Defining the Joint and CANopen Data Structure
 The first step is to define a structure that will hold information about your joints and the associated CANopen data. This structure serves as the foundation for  your CANopen network, ensuring that all the relevant data is stored and accessible when needed.

PDO Index and Subindex
 Each Process Data Object (PDO) has an index and a subindex. The index acts as a unique identifier for each PDO, differentiating it from other PDOs in the system. The subindex is used to access individual data fields within each PDO as a PDO can contain multiple data fields.

Network Management (NMT)
 Network Management (NMT) is a fundamental service in the CANopen protocol suite. It offers basic device control commands such as start, stop, and reset, and manages the state of devices within the network.

 For RPDOs, the data are defined using:

 - "rpdo/index"
 - "rpdo/subindex"
 - "rpdo/type"
 - "rpdo/data"

 For NMT, we can read the states via:

 - "nmt/state"


Use TPDO to send commands
----------------------------
In order to send commands to hardware devices in a CANopen network, we first need to export the appropriate hardware interfaces. This is a critical step that enables us to effectively control each joint within our network.

Registering Transmit Process Data Objects (TPDOs)
 Similar to how we handle state interfaces, we must register Transmit Process Data Objects (TPDOs) for each joint. These TPDOs are related to the following commands:

- "tpdo/index"
- "tpdo/subindex"
- "tpdo/type"
- "tpdo/data"
- "tpdo/owns"

Network Management (NMT) Commands
 Beyond this, we have the ability to register commands associated with Network Management (NMT) to control the state of devices within our network. This is important for the smooth operation and control of our devices. The NMT related commands include:

- "nmt/reset"
- "nmt/reset_fbk"
- "nmt/start"
- "nmt/start_fbk"

These NMT commands not only help in managing the state of devices but also in providing feedback (indicated by "fbk") from the device to the control system after the execution of a command. This feedback mechanism is crucial for ensuring the successful execution of commands and managing the overall health of the network.


How to launch the nodes
----------------------------
Finally, we prepare the launch file for the interface. An example see: https://github.com/ros-industrial/ros2_canopen/blob/master/canopen_ros2_control/launch/canopen_system.launch.py

For testing, please refer to following section.


================================================
FILE: canopen/sphinx/user-guide/how-to-create-a-configuration.rst
================================================
How to create a configuration package
========================================
In order to use the ros2_canopen stack for your robot, you need to
create a configuration package, that holds the configuration of the
bus as well as you launch script. The following sections detail the
steps to create such a package.


Package creation
----------------
When you create your package, you have to first make some decisions.
You will need to choose a package name, decide which bus configurations
you need to have (usually one per CAN interface) and which slaves you have.

| **package_name**: Name of the package
| **bus_config_name**: Name of the the bus configuration (you can have multiple)

You can use ``ros2 pkg create`` command to create your package.

.. code-block:: console

  $ ros2 pkg create --dependencies canopen lely_core_libraries --build-type ament_cmake {package_name}
  $ cd {package_name}
  $ rm -rf src
  $ rm -rf include
  $ mkdir -p launch
  $ mkdir -p config

Now your package directory should look like this.

::

      {package_name}
      ├── config
      ├── launch
      ├── CMakeLists.txt
      └── package.xml



Bus configuration creation
------------------------------

#. **Bus configuration decisions**
    Decide how many bus configurations you need. Add one subfolder for each
    bus configuration in your `config`-folder.

    .. code-block:: bash

      $ mkdir -p {bus_config_name}

#. **Add device information to bus configurations**
    Once you created the folders for your bus configurations add the .eds files
    for the devices that are in the bus configuration to the respective folder.

    Now your package directory should now look like this.

    ::

          {package_name}
          ├── config
          │   ├── {bus_config_name_1}
          │   |   ├── {device1}.eds
          │   |   ├── {device...}.eds
          │   |   └── {slave_n}.eds
          │   └── {bus_config_name_2}
          │       ├── {device1}.eds
          │       ├── {device...}.eds
          │       └── {slave_n}.eds
          ├── CMakeLists.txt
          └── package.xml

#. **Create the bus configuration specifications**
    To specify the bus configuration ros2_canopen uses the a YAML-file called
    bus.yml. Create the file in the respective bus configuration folder.

    .. code-block:: console

      $ touch bus.yml

    ::

          {package_name}
          ├── config
          │   ├── {bus_config_name_1}
          │   |   ├── bus.yml
          │   |   ├── {device1}.eds
          │   |   ├── {device...}.eds
          │   |   └── {slave_n}.eds
          │   └── {bus_config_name_2}
          │       ├── bus.yml
          │       ├── {device1}.eds
          │       ├── {device...}.eds
          │       └── {slave_n}.eds
          ├── CMakeLists.txt
          └── package.xml

#. **Edit the bus configuration specifications**
    You need to modify each bus.yml file according to your needs.
    First you need to define where these files and generated files will be
    found at runtime. This is usually the following if you use colcon to
    build from source.

    .. code-block:: yaml

      options:
        dcf_path: install/{package_name}/share/{package_name}/config/{bus_config_name}

    Then you need to define your master.

    .. code-block:: yaml

      master:
        node_id: [node id]
        package: [ros2 package where to find the master driver (usually canopen_core)]
        driver: [component type of the driver (ros2_canopen::MasterDriver or ros2_canopen::LifecycleMasterDriver)]

    Make sure, that you specify a lifecycle master if you use the lifecycled version of ros2_canopen.
    And add other configuration data as necessary. A documentation of configuration options
    available can be found in the :doc:`configuration` documentation.

    Once you have defined the configuration of your master, add your slaves. The following
    describes the mandatory data per slave. Further configuration options can be found in the :doc:`configuration` documentation.
    The slave name is the node name that will be assigned to the driver.

    .. code-block:: yaml

      nodes:
        - [unique slave name]:
          node_id: [node id]
          package: [ros2 package where to find the driver]
          driver: [qualified name of the driver]

    Make sure you use a lifecycle slave if you use the lifecycled version of ros2_canopen.


Launch configuration creation
-----------------------------

Create a launch folder in your package directory and a launch file.

.. code-block:: console

  mkdir launch
  touch {...}.launch.py

Add the following code:

.. code-block:: python

  def generate_launch_description():
        """Generate launch description with multiple components."""
        path_file = os.path.dirname(__file__)

        ld = launch.LaunchDescription()


        device_container = IncludeLaunchDescription(
            PythonLaunchDescriptionSource(
                [
                    os.path.join(get_package_share_directory("canopen_core"), "launch"),
                    "/canopen.launch.py",
                ]
            ),
            launch_arguments={
                "master_config": os.path.join(
                    get_package_share_directory("{package_name}"),
                    "config",
                    "{bus_config_name}",
                    "master.dcf",
                ),
                "master_bin": os.path.join(
                    get_package_share_directory("{package_name}"),
                    "config",
                    "{bus_config_name}",
                    "master.bin",
                ),
                "bus_config": os.path.join(
                    get_package_share_directory("{package_name}"),
                    "config",
                    "{bus_config_name}",
                    "bus.yml",
                ),
                "can_interface_name": "{can_interface_name i.e. can0}",
            }.items(),

        )

        ld.add_action(device_container)

        return ld


CMAKE Configuration creation
-----------------------------
Finally we need to adjust the CMakeLists.txt file to pick everything up correctly.

.. code-block:: cmake

  cmake_minimum_required(VERSION 3.8)
  project({package_name})

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

  # find dependencies
  find_package(ament_cmake REQUIRED)
  find_package(canopen_core REQUIRED)
  find_package(canopen_interfaces REQUIRED)
  find_package(canopen_base_driver REQUIRED)
  find_package(canopen_proxy_driver REQUIRED)
  find_package(lely_core_libraries REQUIRED)


  cogen_dcf({bus_config_name})

  install(DIRECTORY
    launch/
    DESTINATION share/${PROJECT_NAME}/launch/
  )

  install(DIRECTORY
    launch_tests/
    DESTINATION share/${PROJECT_NAME}/launch_tests/
  )


  if(BUILD_TESTING)
    find_package(ament_lint_auto REQUIRED)
    # the following line skips the linter which checks for copyrights
    # comment the line when a copyright and license is added to all source files
    set(ament_cmake_copyright_FOUND TRUE)
    # the following line skips cpplint (only works in a git repo)
    # comment the line when this package is in a git repo and when
    # a copyright and license is added to all source files
    set(ament_cmake_cpplint_FOUND TRUE)
    ament_lint_auto_find_test_dependencies()
  endif()

  ament_package()


================================================
FILE: canopen/sphinx/user-guide/how-to-create-a-robot-system.rst
================================================
How to create a robot system with ros2_control
==============================================
This guide describes how to create a simple robot using the robot system hardware interface
leveragin ros2_control.

1. Create a new configuration package with the name ``canopen_robot_control_example``.

  .. code-block:: console

    $ ros2 pkg create --dependencies canopen lely_core_libraries --build-type ament_cmake {package_name}
    $ cd {package_name}
    $ rm -rf src
    $ rm -rf include
    $ mkdir -p launch
    $ mkdir -p config

2. Create a new bus configuration folder with the name ``robot_control``.

  .. code-block:: console

    $ mkdir -p config/robot_control

3. Create a new bus configuration file with the name ``bus.yml``.

  .. code-block:: console

    $ touch config/robot_control/bus.yml

4. Add the following content to the ``bus.yml`` file.

.. code-block:: yaml

  options:
    dcf_path: "@BUS_CONFIG_PATH@"

  master:
    node_id: 1
    driver: "ros2_canopen::MasterDriver"
    package: "canopen_master_driver"
    sync_period: 10000

  defaults:
    dcf: "cia402_slave.eds"
    driver: "ros2_canopen::Cia402Driver"
    package: "canopen_402_driver"
    period: 10
    position_mode: 1
    revision_number: 0
    sdo:
      - {index: 0x60C2, sub_index: 1, value: 50} # Set interpolation time for cyclic modes to 50 ms
      - {index: 0x60C2, sub_index: 2, value: -3} # Set base 10-3s
      - {index: 0x6081, sub_index: 0, value: 1000}
      - {index: 0x6083, sub_index: 0, value: 2000}
      - {index: 0x6060, sub_index: 0, value: 7}
    tpdo: # TPDO needed statusword, actual velocity, actual position, mode of operation
      1:
        enabled: true
        cob_id: "auto"
        transmission: 0x01
        mapping:
          - {index: 0x6041, sub_index: 0} # status word
          - {index: 0x6061, sub_index: 0} # mode of operation display
      2:
        enabled: true
        cob_id: "auto"
        transmission: 0x01
        mapping:
          - {index: 0x6064, sub_index: 0} # position actual value
          - {index: 0x606c, sub_index: 0} # velocity actual position
    rpdo: # RPDO needed controlword, target position, target velocity, mode of operation
      1:
        enabled: true
        cob_id: "auto"
        mapping:
        - {index: 0x6040, sub_index: 0} # controlword
        - {index: 0x6060, sub_index: 0} # mode of operation
      2:
        enabled: true
        cob_id: "auto"
        mapping:
        - {index: 0x607A, sub_index: 0} # target position

  nodes:
    joint_1:
      node_id: 2
    joint_2:
      node_id: 3

5. Copy the ``cia402_slave.eds`` file from the ``canopen_tests/config/robot_control`` package to the ``config/robot_control`` folder.

6. Create a ros2_controllers.yaml and add the following content.

.. code-block:: yaml

  controller_manager:
    ros__parameters:
      update_rate: 100  # Hz
      joint_state_broadcaster:
        type: joint_state_broadcaster/JointStateBroadcaster

      forward_position_controller:
        type: forward_command_controller/ForwardCommandController

  forward_position_controller:
    ros__parameters:
      joints:
        - joint1
        - joint2
      interface_name: position

7. Create a launch file with the name ``robot_control.launch.py`` in the launch directory of your package and add the following content.

.. code-block:: python

  from launch import LaunchDescription
  from launch.actions import DeclareLaunchArgument
  from launch.substitutions import Command, FindExecutable, LaunchConfiguration, PathJoinSubstitution
  from launch_ros.actions import Node
  from launch_ros.substitutions import FindPackageShare
  from launch.actions import IncludeLaunchDescription
  from launch.launch_description_sources import PythonLaunchDescriptionSource


  def generate_launch_description():
      robot_description_content = Command(
          [
              PathJoinSubstitution([FindExecutable(name="xacro")]),
              " ",
              PathJoinSubstitution(
                  [
                      FindPackageShare("canopen_tests"),
                      "urdf",
                      "robot_controller",
                      "robot_controller.urdf.xacro",
                  ]
              ),
          ]
      )
      robot_description = {"robot_description": robot_description_content}
      robot_control_config = PathJoinSubstitution(
          [FindPackageShare("canopen_tests"), "config/robot_control", "ros2_controllers.yaml"]
      )

      control_node = Node(
          package="controller_manager",
          executable="ros2_control_node",
          parameters=[robot_description, robot_control_config],
          output="screen",
      )

      joint_state_broadcaster_spawner = Node(
          package="controller_manager",
          executable="spawner",
          arguments=["joint_state_broadcaster", "--controller-manager", "/controller_manager"],
      )

      forward_position_controller_spawner = Node(
          package="controller_manager",
          executable="spawner",
          arguments=["forward_position_controller", "--controller-manager", "/controller_manager"],
      )

      robot_state_publisher_node = Node(
          package="robot_state_publisher",
          executable="robot_state_publisher",
          output="both",
          parameters=[robot_description],
      )

      slave_config = PathJoinSubstitution(
          [FindPackageShare("canopen_tests"), "config/robot_control", "cia402_slave.eds"]
      )

      slave_launch = PathJoinSubstitution(
          [FindPackageShare("canopen_fake_slaves"), "launch", "cia402_slave.launch.py"]
      )
      slave_node_1 = IncludeLaunchDescription(
          PythonLaunchDescriptionSource(slave_launch),
          launch_arguments={
              "node_id": "2",
              "node_name": "slave_node_1",
              "slave_config": slave_config,
          }.items(),
      )

      slave_node_2 = IncludeLaunchDescription(
          PythonLaunchDescriptionSource(slave_launch),
          launch_arguments={
              "node_id": "3",
              "node_name": "slave_node_2",
              "slave_config": slave_config,
          }.items(),
      )

      nodes_to_start = [
          control_node,
          joint_state_broadcaster_spawner,
          forward_position_controller_spawner,
          robot_state_publisher_node,
          slave_node_1,
          slave_node_2
      ]

      return LaunchDescription(nodes_to_start)

8. Create a urdf folder add all files from the ``canopen_tests/urdf/robot_controller`` package to the urdf folder of your package.

9. Edit the CMakeLists.txt file of your package and add the following lines after the find_package section.

.. code-block:: cmake

  cogen_dcf(robot_control)

  install(DIRECTORY
  launch urdf
  DESTINATION share/${PROJECT_NAME})

10. Build your package and source the setup.bash file.
11. Start your launch file
12. You can now control the robot with the forward_command_controller. You can as well visualize the robot in
    rviz by adding a tf or a robot model and setting the fixed frame to ``base_link``. You can move the robot with the
    following command.

.. code-block:: bash

  ros2 topic pub /joint1/forward_position_controller/command std_msgs/msg/Float64 "data: [1.0, 1.0]"


================================================
FILE: canopen/sphinx/user-guide/master.rst
================================================
Master Driver
=============

The master driver handles the creation of the necessary can interface and sets up a canopen event loop which drivers can hook onto.
In addition, the node offers services for communicating with nodes via nmt and sdo.

.. csv-table:: Master Drivers
   :header: Type, Package, Name
   :widths: 30, 20, 50

   lifecycle, canopen_master_driver, ros2_canopen::LifecycleMasterDriver
   simple, canopen_master_driver, ros2_canopen::MasterDriver


Services
--------

.. list-table::
  :widths: 30 20 50
  :header-rows: 1

  * - Services
    - Type
    - Description
  * - ~/read_sdo
    - COReadID
    - Reads an SDO object specified by Index, Subindex and Datatype of the device with the specified nodeid.
  * - ~/write_sdo
    - COWriteID
    - Writes Data to an SDO object specified by Index, Subindex and Datatype on the device with the specified nodeid.
  * - ~/set_nmt
    - CONmtID
    - Sends the NMT command to the device with the specified nodeid


================================================
FILE: canopen/sphinx/user-guide/operation/managed-service-interface.rst
================================================
Managed Service Interface
============================


Device Container with managed nodes
"""""""""""""""""""""""""""""""""""
The device container implements ROS2 component manager. The load and unload services are disabled.
Devices are loaded based on the Bus Configuration File (bus.yml). The device container provides
the list service, which can be used with ros2cli to check which components have been loaded.

.. figure:: ../../images/device-manager.png
    :alt: Device Manager Concept

    device manager concept

The device container uses the bus description file to identify the correct drivers for each devices.
On launch it will load the CANopen master node and driver nodes and pass the appropriate configuration
data to the nodes. The nodes are now in unconfigured state.

When using the default launch files in canopen_core the lifecycle manager node will automatically
be launched. The lifecycle manager takes care of sequencing the lifecycle of the different nodes in the
device container. By bringing the lifecycle_manager to active lifecycle state, all master and driver nodes
will be activated in correct sequence.

If you choose to write your own lifecycle_manager, you'll need to remember, that the master needs
to be configured and activated before any driver node can be configured or activated.


Bus Configuration
"""""""""""""""""
The bus configuration for the managed service interface needs to use the driver classes that are marked as
lifecycle drivers. The master driver indicates whether the bus.yml will be treated as managed or un-managed
service interface.

.. csv-table:: Available Driver Components
   :header: "Package", "Component"

    canopen_master_driver, ros2_canopen::LifecycleMasterDriver
    canopen_proxy_driver, ros2_canopen::LifecycleProxyDriver
    canopen_402_driver, ros2_canopen::LifecycleCia402Driver

Launching
"""""""""""""
The device manager has the following configuration parameters.

.. csv-table:: Parameters
   :header: "Parameter", "Type", "Description"

    bus_conf, string, (Mandatory) Path to the bus configuration YAML-file
    master_dcf, string, (Mandatory) Path to the DCF file to be used by the master node. Usually generated by dcfgen as master.dcf.
    master_bin, string, (Optional) Path to the concise DCF (.bin) file to be used to configure the master. Usually generated by dcfgen as master.bin. (default: "")
    can_interface_name, string, (Mandatory) Name of the CAN interface to be used. (default: vcan0)


================================================
FILE: canopen/sphinx/user-guide/operation/ros2-control-interface.rst
================================================
Hardware Interface
------------------
This package provides multiple hardware interfaces for testing. Mainly the following:

- canopen_ros2_control/CanopenSystem: A system interface for ProxyDrivers
- canopen_ros2_control/Cia402System: A system interface for Cia402Drivers
- canopen_ros2_control/Cia402RobotSystem: A system interface for Cia402Drivers in a robot configuration (under development)


Robot System Interface
''''''''''''''''''''''

The robot system interface takes a number of inputs from the robot description (urdf).
It will make the Cia402Drivers available via the ros2_control hardware interface.
The bus has to still be defined in the bus.yml file. In the urdf you can the choose the
CANopen nodes that have a Cia402Driver attached to them.

The ros2_control interface only works with non-lifecycle drivers right now.
For each joint in your urdf you can choose the attached CANopen device by using the
``node_id`` parameter. The ``node_id`` parameter is the CANopen node id of the device.

.. code-block:: xml

    <ros2_control name="${name}" type="system">
        <hardware>
            <plugin>canopen_ros2_control/Cia402RobotSystem</plugin>
            <param name="bus_config">[path to bus.yml]</param>
            <param name="master_config">[path to master.dcf]</param>
            <param name="can_interface_name">[can interface to be used]</param>
            <param name="master_bin">[master.bin if it exists]</param>
        </hardware>
        <joint name="joint1">
            <param name="node_id">3</param>
            ...
        </joint>
        <joint name="joint2">
            <param name="node_id">3</param>
            ...
        </joint>
    </ros2_control>

.. note::

    You can find an example for the configuration in the ``canopen_tests`` package under robot_control.


ROS2 Controllers
----------------
This package provides multiple controllers for testing. Mainly the following:

- canopen_ros2_controllers/Cia402RobotController: Works with Robot System Interface
- canopen_ros2_controllers/Cia402DeviceController: Works with Cia402System
- canopen_ros2_controllers/CanopenProxyController: Works with CanopenSystem and Cia402System

Robot Controller
''''''''''''''''

The robot controller enables bringing up the different joints of the robot automatically
by using the ros2_controller lifecycle. There is no need for further action, once the
controller is activated, the drives are ready to be used.

The robot controller can be configured in the ros2_controllers.yaml with the following
parameters:

.. code-block:: yaml

    robot_controller:
        ros__parameters:
            joints:  # joints that are controlled by the controller
            - joint1
            - joint2
            operation_mode: 1 # operation mode of the controller
            command_poll_freq: 5 # frequency with which the controller polls for command feedback


================================================
FILE: canopen/sphinx/user-guide/operation/service-interface.rst
================================================
Service Interface
==================


Device Container
"""""""""""""""""
The device container implements ROS2 component manager. The load and unload services are disabled.
Devices are loaded based on the Bus Configuration File (bus.yml). It provides the list service though.

.. figure:: ../../images/device-manager.png
    :alt: Device Manager Concept

    device manager concept

The device manager uses the bus description file to identify the correct drivers for each devices.
On launch it will load the CANopen master node and pass the generated DCF files to configure the CANopen master
correctly for you bus configuration. It will the enable the master. Once the master is enabled it will
sequentially load and enable all drivers in the bus configuration.

Once a CANopen Node comes online (i.e. sends the boot indication) the CANopen master
will configure the node with the parameters and commands specified in the bus configuration for that device.
When the configuration of the device is done, all data send by the device is forwarded
to the appropriate driver.

All loaded nodes are added to the device manager's executor.

.. figure:: ../../images/device-manager-usage.png
    :alt: Device Manager Usage

    device manager usage

Bus Configuration
"""""""""""""""""
The bus configuration for the needs to use the driver classes that are marked as
non lifecycle drivers.

.. csv-table:: Available Driver Components
   :header: "Package", "Component"

    canopen_core, ros2_canopen::MasterDriver
    canopen_proxy_driver, ros2_canopen::ProxyDriver
    canopen_402_driver, ros2_canopen::Cia402Driver

Launching
"""""""""""""
The device manager has the following configuration parameters.

.. csv-table:: Parameters
   :header: "Parameter", "Type", "Description"

    bus_conf, string, (Mandatory) Path to the bus configuration YAML-file
    master_dcf, string, (Mandatory) Path to the DCF file to be used by the master node. Usually generated by dcfgen as master.dcf.
    master_bin, string, (Optional) Path to the concise DCF (.bin) file to be used to configure the master. Usually generated by dcfgen as master.bin. (default: "")
    can_interface_name, string, (Mandatory) Name of the CAN interface to be used. (default: vcan0)


================================================
FILE: canopen/sphinx/user-guide/operation.rst
================================================
Operation
=========

The ros2_canopen stack can be used in three different ways:

* standard nodes container
* managed nodes container
* ros2_control system interface with standard nodes


Simple nodes container
""""""""""""""""""""""""
The standard node container mode bundles the master and all slave driver nodes in one specialised
container called device container. All nodes are simple ROS 2 nodes and expose a publish and subscribe
as well as a service interfaces. Once the device container is started, all nodes are brought up
and ready to be used.

**Purpose**:
The simple nodes container is thought for applications where the user needs a simple and
easy to launch interface and does not need any realtime control capabilities as provided by
ros2_control.

Managed nodes container
""""""""""""""""""""""""""
The managed nodes container has the same properties as the standard nodes container.
The exception is, that all nodes are lifecycle nodes and there is a special node called
lifecycle manager. The user can use the lifecycle manager to control the lifecycle of
all nodes in the container.

**Purpose**:
The managed nodes container is thought for applications where the user wants to have
more runtime recovery options than killing and restarting the container.


ROS 2 control system interface
""""""""""""""""""""""""""""""
The ros2_control interface is currently build on top of the simple nodes container. In
addition to the standard nodes container the ros2_control system interface provides a
hardware interface that can be used to control the devices on the bus. Currently, three
different system interfaces are provided:

* canopen_ros2_control/CANopenSystem
* canopen_ros2_control/CIA402System
* canopen_ros2_control/RobotSystem

**Purpose**:
The ROS 2 control system interfaces are thought for control applications that require
low latencies.


================================================
FILE: canopen/sphinx/user-guide/proxy-driver.rst
================================================
Proxy Driver
===================
A proxy driver which simply forwards CANopen functionality for a specific device via ROS2 services and messages.

.. csv-table:: Proxy Drivers
   :header: Type, Package, Name
   :widths: 30, 20, 50

   lifecycle, canopen_proxy_driver, ros2_canopen::LifecycleProxyDriver
   simple, canopen_proxy_driver, ros2_canopen::ProxyDriver

Services
--------

.. list-table::
  :widths: 30 20 50
  :header-rows: 1
  :align: left

  * - Services
    - Type
    - Description
  * - ~/nmt_reset_node
    - Trigger
    - Resets CANopen Device the Proxy Device Node manages.
  * - ~/sdo_read
    - CORead
    - Reads an SDO object from the specified index, subindex and datatype of the remote device.
  * - ~/sdo_write
    - COWrite
    - Writes data to an SDO object on the specified index, subindex and datatype of the remote device.


Publishers
----------

.. list-table::
  :widths: 30 20 50
  :header-rows: 1
  :align: left

  * - Topic
    - Type
    - Description
  * - ~/nmt_state
    - String
    - Publishes NMT state on change
  * - ~/rpdo
    - COData
    - Publishes received PDO objects on reception

Subscribers
-----------

.. list-table::
  :widths: 30 20 50
  :header-rows: 1

  * - Topic
    - Type
    - Description
  * - ~/tpdo
    - COData
    - Writes received data to remote device if the specified object is RPDO mapped on remote device.


================================================
FILE: canopen_402_driver/CHANGELOG.rst
================================================
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Changelog for package canopen_402_driver
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

0.3.2 (2025-12-05)
------------------
* Fix configuration parsing and logging
* add pdo 6077 torque actual value to the joint state interface as effort (`#316 <https://github.com/ros-industrial/ros2_canopen/issues/316>`_)
* Contributors: ipa-vsp, synsi23b

0.3.1 (2025-06-23)
------------------
* Homing timeout
* Add services to disable/enable motor so that brake is usable.
* Contributors: Vishnuprasad Prachandabhanu

0.3.0 (2024-12-12)
------------------
* Reformat using pre-commit
* Implement position offsets
* pre-commit fix
* impl operation mode
* Add cyclic torque mode to cia402 driver and robot system controller (`#293 <https://github.com/ros-industrial/ros2_canopen/issues/293>`_)
  * Add base functions for switching to cyclic torque mode
  * Add cyclic torque mode as effort interface to robot_system controller
  * Add documentation about cyclic torque mode.
  Co-authored-by: Christoph Hellmann Santos <christoph.hellmann.santos@ipa.fraunhofer.de>

0.2.12 (2024-04-22)
-------------------
* 0.2.9
* forthcoming
* Merge pull request `#267 <https://github.com/ros-industrial/ros2_canopen/issues/267>`_ from clalancette/clalancette/update-lely-core-hash
  Update the lely_core_libraries hash to the latest.
* fix ci build error
* Contributors: Vishnuprasad Prachandabhanu, ipa-vsp

0.2.9 (2024-04-16)
------------------
* Update the lely_core_libraries hash to the latest.
* fix ci build error
* Contributors: Vishnuprasad Prachandabhanu

0.2.8 (2024-01-19)
------------------

0.2.7 (2023-06-30)
------------------
* Add missing license headers and activate ament_copyright
* Fix maintainer naming
* Contributors: Christoph Hellmann Santos

0.2.6 (2023-06-24)
------------------

0.2.5 (2023-06-23)
------------------

0.2.4 (2023-06-22)
------------------

0.2.3 (2023-06-22)
------------------

0.2.2 (2023-06-21)
------------------

0.2.1 (2023-06-21)
------------------
* Fix boost/std placeholders ambiguity in older boost versions
* Contributors: Christoph Hellmann Santos

0.2.0 (2023-06-14)
------------------
* Created package
* Contributors: Borong Yuan, Błażej Sowa, Christoph Hellmann Santos, Denis Štogl, G.A. vd. Hoorn, Lovro, Vishnuprasad Prachandabhanu, livanov93


================================================
FILE: canopen_402_driver/CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.8)
project(canopen_402_driver)

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

# find dependencies
find_package(ament_cmake REQUIRED)
find_package(ament_cmake_ros REQUIRED)
find_package(canopen_base_driver REQUIRED)
find_package(canopen_core REQUIRED)
find_package(canopen_interfaces REQUIRED)
find_package(canopen_proxy_driver REQUIRED)
find_package(rclcpp REQUIRED)
find_package(rclcpp_components REQUIRED)
find_package(rclcpp_lifecycle REQUIRED)
find_package(sensor_msgs REQUIRED)

add_library(lely_motion_controller_bridge
  src/motor.cpp
  src/command.cpp
  src/state.cpp
  src/default_homing_mode.cpp
)
target_compile_features(lely_motion_controller_bridge PUBLIC c_std_99 cxx_std_17)  # Require C99 and C++17
target_compile_options(lely_motion_controller_bridge PUBLIC -Wl,--no-undefined)
target_include_directories(lely_motion_controller_bridge PUBLIC
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
  $<INSTALL_INTERFACE:include>)

target_link_libraries(lely_motion_controller_bridge PUBLIC
  canopen_base_driver::node_canopen_base_driver
  rclcpp::rclcpp
)


add_library(node_canopen_cia402_driver
  src/node_interfaces/node_canopen_402_driver.cpp
)
target_compile_features(node_canopen_cia402_driver PUBLIC c_std_99 cxx_std_17)  # Require C99 and C++17
target_compile_options(node_canopen_cia402_driver PUBLIC -Wl,--no-undefined)
target_include_directories(node_canopen_cia402_driver PUBLIC
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
  $<INSTALL_INTERFACE:include>)
target_link_libraries(node_canopen_cia402_driver PUBLIC
  ${canopen_interfaces_TARGETS}
  ${sensor_msgs_TARGETS}
  canopen_proxy_driver::node_canopen_proxy_driver
  lely_motion_controller_bridge
)

add_library(lifecycle_cia402_driver
  src/lifecycle_cia402_driver.cpp
)
target_compile_features(lifecycle_cia402_driver PUBLIC c_std_99 cxx_std_17)  # Require C99 and C++17
target_compile_options(lifecycle_cia402_driver PUBLIC -Wl,--no-undefined)
target_include_directories(lifecycle_cia402_driver PUBLIC
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
  $<INSTALL_INTERFACE:include>)

target_link_libraries(lifecycle_cia402_driver PUBLIC
  canopen_core::node_canopen_driver
  node_canopen_cia402_driver
  rclcpp_components::component
  rclcpp_lifecycle::rclcpp_lifecycle
)
# Causes the visibility macros to use dllexport rather than dllimport,
# which is appropriate when building the dll but not consuming it.
target_compile_definitions(lifecycle_cia402_driver PRIVATE "CANOPEN_402_DRIVER_BUILDING_LIBRARY")

rclcpp_components_register_nodes(lifecycle_cia402_driver "ros2_canopen::LifecycleCia402Driver")
set(node_plugins "${node_plugins}ros2_canopen::LifecycleCia402Driver;$<TARGET_FILE:lifecycle_cia402_driver>\n")




add_library(cia402_driver
  src/cia402_driver.cpp
)
target_compile_features(cia402_driver PUBLIC c_std_99 cxx_std_17)  # Require C99 and C++17
target_compile_options(cia402_driver PUBLIC -Wl,--no-undefined)
target_include_directories(cia402_driver PUBLIC
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
  $<INSTALL_INTERFACE:include>)
target_link_libraries(cia402_driver PUBLIC
  canopen_core::node_canopen_driver
  node_canopen_cia402_driver
  rclcpp_components::component
)

# Causes the visibility macros to use dllexport rather than dllimport,
# which is appropriate when building the dll but not consuming it.
target_compile_definitions(cia402_driver PRIVATE "CANOPEN_cia402_driver_BUILDING_LIBRARY")

rclcpp_components_register_nodes(cia402_driver "ros2_canopen::Cia402Driver")
set(node_plugins "${node_plugins}ros2_canopen::Cia402Driver;$<TARGET_FILE:cia402_driver>\n")

install(
  DIRECTORY include/
  DESTINATION include
)

install(
  TARGETS lifecycle_cia402_driver cia402_driver node_canopen_cia402_driver lely_motion_controller_bridge
  EXPORT export_${PROJECT_NAME}
  ARCHIVE DESTINATION lib
  LIBRARY DESTINATION lib
  RUNTIME DESTINATION bin
)

if(BUILD_TESTING)
  find_package(ament_cmake_gtest REQUIRED)
  add_subdirectory(test)
endif()

ament_export_include_directories(
  include
)
ament_export_libraries(
  lifecycle_cia402_driver
  cia402_driver
  node_canopen_cia402_driver
  lely_motion_controller_bridge
)
ament_export_targets(
  export_${PROJECT_NAME}
)
ament_export_dependencies(
  canopen_base_driver
  canopen_core
  canopen_interfaces
  canopen_proxy_driver
  rclcpp
  rclcpp_components
  rclcpp_lifecycle
  sensor_msgs
)

ament_package()


================================================
FILE: canopen_402_driver/LICENSE
================================================
GNU LESSER GENERAL PUBLIC LICENSE
                       Version 3, 29 June 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.


  This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.

  0. Additional Definitions.

  As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.

  "The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.

  An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.

  A "Combined Work" is a work produced by combining or linking an
Application with the Library.  The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".

  The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.

  The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.

  1. Exception to Section 3 of the GNU GPL.

  You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.

  2. Conveying Modified Versions.

  If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:

   a) under this License, provided that you make a good faith effort to
   ensure that, in the event an Application does not supply the
   function or data, the facility still operates, and performs
   whatever part of its purpose remains meaningful, or

   b) under the GNU GPL, with none of the additional permissions of
   this License applicable to that copy.

  3. Object Code Incorporating Material from Library Header Files.

  The object code form of an Application may incorporate material from
a header file that is part of the Library.  You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:

   a) Give prominent notice with each copy of the object code that the
   Library is used in it and that the Library and its use are
   covered by this License.

   b) Accompany the object code with a copy of the GNU GPL and this license
   document.

  4. Combined Works.

  You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:

   a) Give prominent notice with each copy of the Combined Work that
   the Library is used in it and that the Library and its use are
   covered by this License.

   b) Accompany the Combined Work with a copy of the GNU GPL and this license
   document.

   c) For a Combined Work that displays copyright notices during
   execution, include the copyright notice for the Library among
   these notices, as well as a reference directing the user to the
   copies of the GNU GPL and this license document.

   d) Do one of the following:

       0) Convey the Minimal Corresponding Source under the terms of this
       License, and the Corresponding Application Code in a form
       suitable for, and under terms that permit, the user to
       recombine or relink the Application with a modified version of
       the Linked Version to produce a modified Combined Work, in the
       manner specified by section 6 of the GNU GPL for conveying
       Corresponding Source.

       1) Use a suitable shared library mechanism for linking with the
       Library.  A suitable mechanism is one that (a) uses at run time
       a copy of the Library already present on the user's computer
       system, and (b) will operate properly with a modified version
       of the Library that is interface-compatible with the Linked
       Version.

   e) Provide Installation Information, but only if you would otherwise
   be required to provide such information under section 6 of the
   GNU GPL, and only to the extent that such information is
   necessary to install and execute a modified version of the
   Combined Work produced by recombining or relinking the
   Application with a modified version of the Linked Version. (If
   you use option 4d0, the Installation Information must accompany
   the Minimal Corresponding Source and Corresponding Application
   Code. If you use option 4d1, you must provide the Installation
   Information in the manner specified by section 6 of the GNU GPL
   for conveying Corresponding Source.)

  5. Combined Libraries.

  You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:

   a) Accompany the combined library with a copy of the same work based
   on the Library, uncombined with any other library facilities,
   conveyed under the terms of this License.

   b) Give prominent notice with the combined library that part of it
   is a work based on the Library, and explaining where to find the
   accompanying uncombined form of the same work.

  6. Revised Versions of the GNU Lesser General Public License.

  The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.

  Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.

  If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.


================================================
FILE: canopen_402_driver/include/canopen_402_driver/base.hpp
================================================
//    Copyright 2023 Christoph Hellmann Santos
//    Copyright 2014-2022 Authors of ros_canopen
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//
#ifndef CANOPEN_402_BASE_H
#define CANOPEN_402_BASE_H
#include <string>

#include "lely/coapp/driver.hpp"
#include "lely/coapp/master.hpp"

namespace ros2_canopen
{

/**
 * @brief Motor Base Class
 *
 */
class MotorBase
{
protected:
  MotorBase() {}

public:
  enum OperationMode
  {
    No_Mode = 0,
    Profiled_Position = 1,
    Velocity = 2,
    Profiled_Velocity = 3,
    Profiled_Torque = 4,
    Reserved = 5,
    Homing = 6,
    Interpolated_Position = 7,
    Cyclic_Synchronous_Position = 8,
    Cyclic_Synchronous_Velocity = 9,
    Cyclic_Synchronous_Torque = 10,
  };

  /**
   * @brief Set target
   *
   * @param [in] val      Target value
   * @return true
   * @return false
   */
  virtual bool setTarget(double val) = 0;

  /**
   * @brief Enter Operation Mode
   *
   * @param [in] mode     Target Mode
   * @return true
   * @return false
   */
  virtual bool enterModeAndWait(uint16_t mode) = 0;

  /**
   * @brief Check if Operation Mode is supported
   *
   * @param [in] mode     Operation Mode to be checked
   * @return true
   * @return false
   */
  virtual bool isModeSupported(uint16_t mode) = 0;

  /**
   * @brief Get current Mode
   *
   * @return uint16_t
   */
  virtual uint16_t getMode() = 0;

  /**
   * @brief Register default Operation Modes
   *
   */
  virtual void registerDefaultModes() {}

  typedef std::shared_ptr<MotorBase> MotorBaseSharedPtr;
};
typedef MotorBase::MotorBaseSharedPtr MotorBaseSharedPtr;

}  // namespace ros2_canopen

#endif


================================================
FILE: canopen_402_driver/include/canopen_402_driver/cia402_driver.hpp
================================================
//    Copyright 2023 Christoph Hellmann Santos
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//

#ifndef CANOPEN_402_DRIVER__402_DRIVER_HPP_
#define CANOPEN_402_DRIVER__402_DRIVER_HPP_
#include <cstdint>
#include "canopen_402_driver/node_interfaces/node_canopen_402_driver.hpp"
#include "canopen_core/driver_node.hpp"

namespace ros2_canopen
{
/**
 * @brief Abstract Class for a CANopen Device Node
 *
 * This class provides the base functionality for creating a
 * CANopen device node. It provides callbacks for nmt and rpdo.
 */
class Cia402Driver : public ros2_canopen::CanopenDriver
{
  std::shared_ptr<node_interfaces::NodeCanopen402Driver<rclcpp::Node>> node_canopen_402_driver_;

public:
  Cia402Driver(rclcpp::NodeOptions node_options = rclcpp::NodeOptions());

  virtual bool reset_node_nmt_command()
  {
    return node_canopen_402_driver_->reset_node_nmt_command();
  }

  virtual bool start_node_nmt_command()
  {
    return node_canopen_402_driver_->start_node_nmt_command();
  }

  virtual bool tpdo_transmit(ros2_canopen::COData & data)
  {
    return node_canopen_402_driver_->tpdo_transmit(data);
  }

  virtual bool sdo_write(ros2_canopen::COData & data)
  {
    return node_canopen_402_driver_->sdo_write(data);
  }

  virtual bool sdo_read(ros2_canopen::COData & data)
  {
    return node_canopen_402_driver_->sdo_read(data);
  }

  void register_nmt_state_cb(std::function<void(canopen::NmtState, uint8_t)> nmt_state_cb)
  {
    node_canopen_402_driver_->register_nmt_state_cb(nmt_state_cb);
  }

  void register_rpdo_cb(std::function<void(COData, uint8_t)> rpdo_cb)
  {
    node_canopen_402_driver_->register_rpdo_cb(rpdo_cb);
  }

  double get_effort(uint8_t channel = 0) { return node_canopen_402_driver_->get_effort(channel); }

  double get_speed(uint8_t channel = 0) { return node_canopen_402_driver_->get_speed(channel); }

  double get_position(uint8_t channel = 0)
  {
    return node_canopen_402_driver_->get_position(channel);
  }

  bool set_target(double target, uint8_t channel = 0)
  {
    return node_canopen_402_driver_->set_target(target, channel);
  }

  bool init_motor(uint8_t channel = 0) { return node_canopen_402_driver_->init_motor(channel); }

  bool recover_motor(uint8_t channel = 0)
  {
    return node_canopen_402_driver_->recover_motor(channel);
  }

  bool halt_motor(uint8_t channel = 0) { return node_canopen_402_driver_->halt_motor(channel); }

  uint16_t get_mode(uint8_t channel = 0) { return node_canopen_402_driver_->get_mode(channel); }

  bool set_operation_mode(uint16_t mode, uint8_t channel = 0)
  {
    return node_canopen_402_driver_->set_operation_mode(mode, channel);
  }
};
}  // namespace ros2_canopen

#endif  // CANOPEN_402_DRIVER__CANOPEN_402_DRIVER_HPP_


================================================
FILE: canopen_402_driver/include/canopen_402_driver/command.hpp
================================================
//    Copyright 2023 Christoph Hellmann Santos
//    Copyright 2014-2022 Authors of ros_canopen
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//

#ifndef CANOPEN_402_DRIVER_COMMAND_HPP
#define CANOPEN_402_DRIVER_COMMAND_HPP

#include <boost/container/flat_map.hpp>
#include <cstdint>
#include <utility>
#include "state.hpp"

namespace ros2_canopen
{
class Command402
{
  struct Op
  {
    uint16_t to_set_;
    uint16_t to_reset_;
    Op(uint16_t to_set, uint16_t to_reset) : to_set_(to_set), to_reset_(to_reset) {}
    void operator()(uint16_t & val) const { val = (val & ~to_reset_) | to_set_; }
  };
  class TransitionTable
  {
    boost::container::flat_map<std::pair<State402::InternalState, State402::InternalState>, Op>
      transitions_;
    void add(const State402::InternalState & from, const State402::InternalState & to, Op op)
    {
      transitions_.insert(std::make_pair(std::make_pair(from, to), op));
    }

  public:
    TransitionTable();
    const Op & get(const State402::InternalState & from, const State402::InternalState & to) const
    {
      return transitions_.at(std::make_pair(from, to));
    }
  };
  static const TransitionTable transitions_;
  static State402::InternalState nextStateForEnabling(State402::InternalState state);
  Command402();

public:
  enum ControlWord
  {
    CW_Switch_On = 0,
    CW_Enable_Voltage = 1,
    CW_Quick_Stop = 2,
    CW_Enable_Operation = 3,
    CW_Operation_mode_specific0 = 4,
    CW_Operation_mode_specific1 = 5,
    CW_Operation_mode_specific2 = 6,
    CW_Fault_Reset = 7,
    CW_Halt = 8,
    CW_Operation_mode_specific3 = 9,
    // CW_Reserved1=10,
    CW_Manufacturer_specific0 = 11,
    CW_Manufacturer_specific1 = 12,
    CW_Manufacturer_specific2 = 13,
    CW_Manufacturer_specific3 = 14,
    CW_Manufacturer_specific4 = 15,
  };
  static bool setTransition(
    uint16_t & cw, const State402::InternalState & from, const State402::InternalState & to,
    State402::InternalState * next);
};
}  // namespace ros2_canopen

#endif  // CANOPEN_402_DRIVER_COMMAND_HPP


================================================
FILE: canopen_402_driver/include/canopen_402_driver/default_homing_mode.hpp
================================================
//    Copyright 2023 Christoph Hellmann Santos
//    Copyright 2014-2022 Authors of ros_canopen
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//

#ifndef DEFAULT_HOMING_MODE_HPP
#define DEFAULT_HOMING_MODE_HPP
#include <mutex>
#include "canopen_base_driver/lely_driver_bridge.hpp"
#include "homing_mode.hpp"

namespace ros2_canopen
{

class DefaultHomingMode : public HomingMode
{
  const uint16_t base_index = 0x6098;
  uint16_t channel_offset_;  // Channel offset for multi-axis support (CiA 402-2)
  std::shared_ptr<LelyDriverBridge> driver;

  std::atomic<bool> execute_;

  std::mutex mutex_;
  std::condition_variable cond_;
  uint16_t status_;

  const int homing_timeout_seconds_;

  enum SW_masks
  {
    MASK_Reached = (1 << State402::SW_Target_reached),
    MASK_Attained = (1 << SW_Attained),
    MASK_Error = (1 << SW_Error),
  };
  bool error(const std::string & msg)
  {
    execute_ = false;
    std::cout << msg << std::endl;
    return false;
  }

public:
  DefaultHomingMode(
    std::shared_ptr<LelyDriverBridge> driver, int homing_timeout_seconds,
    uint16_t channel_offset = 0)
  : homing_timeout_seconds_(homing_timeout_seconds), channel_offset_(channel_offset)
  {
    this->driver = driver;
  }
  virtual bool start();
  virtual bool read(const uint16_t & sw);
  virtual bool write(OpModeAccesser & cw);

  virtual bool executeHoming();
};
}  // namespace ros2_canopen
#endif  // DEFAULT_HOMING_MODE_HPP


================================================
FILE: canopen_402_driver/include/canopen_402_driver/homing_mode.hpp
================================================
//    Copyright 2023 Christoph Hellmann Santos
//    Copyright 2014-2022 Authors of ros_canopen
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//

#ifndef HOMING_MODE_HPP
#define HOMING_MODE_HPP
#include "base.hpp"
#include "mode.hpp"

namespace ros2_canopen
{
class HomingMode : public Mode
{
protected:
  enum SW_bits
  {
    SW_Attained = State402::SW_Operation_mode_specific0,
    SW_Error = State402::SW_Operation_mode_specific1,
  };
  enum CW_bits
  {
    CW_StartHoming = Command402::CW_Operation_mode_specific0,
  };

public:
  HomingMode() : Mode(MotorBase::Homing) {}
  virtual bool executeHoming() = 0;
};
}  // namespace ros2_canopen

#endif  // HOMING_MODE_HPP


================================================
FILE: canopen_402_driver/include/canopen_402_driver/lifecycle_cia402_driver.hpp
================================================
//    Copyright 2023 Christoph Hellmann Santos
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//

#ifndef CANOPEN_402_DRIVER__CANOPEN_LIFECYCLE_402_DRIVER_HPP_
#define CANOPEN_402_DRIVER__CANOPEN_LIFECYCLE_402_DRIVER_HPP_

#include "canopen_402_driver/node_interfaces/node_canopen_402_driver.hpp"
#include "canopen_core/driver_node.hpp"

namespace ros2_canopen
{
/**
 * @brief Lifecycle 402 Driver
 *
 * A very basic driver without any functionality.
 *
 */
class LifecycleCia402Driver : public ros2_canopen::LifecycleCanopenDriver
{
  std::shared_ptr<node_interfaces::NodeCanopen402Driver<rclcpp_lifecycle::LifecycleNode>>
    node_canopen_402_driver_;

public:
  LifecycleCia402Driver(rclcpp::NodeOptions node_options = rclcpp::NodeOptions());

  virtual bool reset_node_nmt_command()
  {
    return node_canopen_402_driver_->reset_node_nmt_command();
  }

  virtual bool start_node_nmt_command()
  {
    return node_canopen_402_driver_->start_node_nmt_command();
  }

  virtual bool tpdo_transmit(ros2_canopen::COData & data)
  {
    return node_canopen_402_driver_->tpdo_transmit(data);
  }

  virtual bool sdo_write(ros2_canopen::COData & data)
  {
    return node_canopen_402_driver_->sdo_write(data);
  }

  virtual bool sdo_read(ros2_canopen::COData & data)
  {
    return node_canopen_402_driver_->sdo_read(data);
  }

  void register_nmt_state_cb(std::function<void(canopen::NmtState, uint8_t)> nmt_state_cb)
  {
    node_canopen_402_driver_->register_nmt_state_cb(nmt_state_cb);
  }

  void register_rpdo_cb(std::function<void(COData, uint8_t)> rpdo_cb)
  {
    node_canopen_402_driver_->register_rpdo_cb(rpdo_cb);
  }

  double get_speed() { return node_canopen_402_driver_->get_speed(); }

  double get_position() { return node_canopen_402_driver_->get_position(); }

  bool set_target(double target) { return node_canopen_402_driver_->set_target(target); }

  bool init_motor() { return node_canopen_402_driver_->init_motor(); }

  bool recover_motor() { return node_canopen_402_driver_->recover_motor(); }

  bool halt_motor() { return node_canopen_402_driver_->halt_motor(); }

  uint16_t get_mode() { return node_canopen_402_driver_->get_mode(); }

  bool set_operation_mode(uint16_t mode)
  {
    return node_canopen_402_driver_->set_operation_mode(mode);
  }
};
}  // namespace ros2_canopen

#endif  // CANOPEN_402_DRIVER__CANOPEN_402_DRIVER_HPP_


================================================
FILE: canopen_402_driver/include/canopen_402_driver/mode.hpp
================================================
//    Copyright 2023 Christoph Hellmann Santos
//    Copyright 2014-2022 Authors of ros_canopen
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//

#ifndef CANOPEN_402_DRIVER_MODE_HPP
#define CANOPEN_402_DRIVER_MODE_HPP

#include <cstdint>
#include <memory>
#include "command.hpp"
#include "state.hpp"
#include "word_accessor.hpp"

namespace ros2_canopen
{
class Mode
{
public:
  const uint16_t mode_id_;
  Mode(uint16_t id) : mode_id_(id) {}
  typedef WordAccessor<
    (1 << Command402::CW_Operation_mode_specific0) |
    (1 << Command402::CW_Operation_mode_specific1) |
    (1 << Command402::CW_Operation_mode_specific2) | (1 << Command402::CW_Operation_mode_specific3)>
    OpModeAccesser;
  virtual bool start() = 0;
  virtual bool read(const uint16_t & sw) = 0;
  virtual bool write(OpModeAccesser & cw) = 0;
  virtual bool setTarget(const double & val) { return false; }
  virtual ~Mode() {}
};
typedef std::shared_ptr<Mode> ModeSharedPtr;
}  // namespace ros2_canopen

#endif  // CANOPEN_402_DRIVER_MODE_HPP


================================================
FILE: canopen_402_driver/include/canopen_402_driver/mode_forward_helper.hpp
================================================
//    Copyright 2023 Christoph Hellmann Santos
//    Copyright 2014-2022 Authors of ros_canopen
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//

#ifndef MODE_FORWARD_HELPER_HPP
#define MODE_FORWARD_HELPER_HPP

#include <cstdint>
#include <memory>
#include "canopen_base_driver/lely_driver_bridge.hpp"
#include "mode_target_helper.hpp"

namespace ros2_canopen
{

template <uint16_t ID, typename TYPE, uint16_t OBJ, uint8_t SUB, uint16_t CW_MASK>
class ModeForwardHelper : public ModeTargetHelper<TYPE>
{
  std::shared_ptr<LelyDriverBri
Download .txt
gitextract_xhwsmvzo/

├── .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
│       ├── prerelease-rolling.yml
│       ├── rolling.yml
│       └── rolling_documentation.yml
├── .gitignore
├── .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
│       ├── 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/
│           │   ├── managed-service-interface.rst
│           │   ├── ros2-control-interface.rst
│           │   └── service-interface.rst
│           ├── operation.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_multichannel_system/
│   │   │   ├── README.md
│   │   │   ├── bus.yml
│   │   │   └── ros2_controllers.yaml
│   │   ├── 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
Download .txt
SYMBOL INDEX (859 symbols across 126 files)

FILE: canopen/sphinx/conf.py
  function get_package (line 57) | def get_package(package: str):

FILE: canopen_402_driver/include/canopen_402_driver/base.hpp
  type ros2_canopen (line 24) | namespace ros2_canopen
    class MotorBase (line 31) | class MotorBase
      method MotorBase (line 34) | MotorBase() {}
      type OperationMode (line 37) | enum OperationMode
      method registerDefaultModes (line 90) | virtual void registerDefaultModes() {}

FILE: canopen_402_driver/include/canopen_402_driver/cia402_driver.hpp
  type ros2_canopen (line 23) | namespace ros2_canopen
    class Cia402Driver (line 31) | class Cia402Driver : public ros2_canopen::CanopenDriver
      method reset_node_nmt_command (line 38) | virtual bool reset_node_nmt_command()
      method start_node_nmt_command (line 43) | virtual bool start_node_nmt_command()
      method tpdo_transmit (line 48) | virtual bool tpdo_transmit(ros2_canopen::COData & data)
      method sdo_write (line 53) | virtual bool sdo_write(ros2_canopen::COData & data)
      method sdo_read (line 58) | virtual bool sdo_read(ros2_canopen::COData & data)
      method register_nmt_state_cb (line 63) | void register_nmt_state_cb(std::function<void(canopen::NmtState, uin...
      method register_rpdo_cb (line 68) | void register_rpdo_cb(std::function<void(COData, uint8_t)> rpdo_cb)
      method get_effort (line 73) | double get_effort(uint8_t channel = 0) { return node_canopen_402_dri...
      method get_speed (line 75) | double get_speed(uint8_t channel = 0) { return node_canopen_402_driv...
      method get_position (line 77) | double get_position(uint8_t channel = 0)
      method set_target (line 82) | bool set_target(double target, uint8_t channel = 0)
      method init_motor (line 87) | bool init_motor(uint8_t channel = 0) { return node_canopen_402_drive...
      method recover_motor (line 89) | bool recover_motor(uint8_t channel = 0)
      method halt_motor (line 94) | bool halt_motor(uint8_t channel = 0) { return node_canopen_402_drive...
      method get_mode (line 96) | uint16_t get_mode(uint8_t channel = 0) { return node_canopen_402_dri...
      method set_operation_mode (line 98) | bool set_operation_mode(uint16_t mode, uint8_t channel = 0)

FILE: canopen_402_driver/include/canopen_402_driver/command.hpp
  type ros2_canopen (line 26) | namespace ros2_canopen
    class Command402 (line 28) | class Command402
      type Op (line 30) | struct Op
        method Op (line 34) | Op(uint16_t to_set, uint16_t to_reset) : to_set_(to_set), to_reset...
      class TransitionTable (line 37) | class TransitionTable
        method add (line 41) | void add(const State402::InternalState & from, const State402::Int...
        method Op (line 48) | const Op & get(const State402::InternalState & from, const State40...
      type ControlWord (line 58) | enum ControlWord

FILE: canopen_402_driver/include/canopen_402_driver/default_homing_mode.hpp
  type ros2_canopen (line 24) | namespace ros2_canopen
    class DefaultHomingMode (line 27) | class DefaultHomingMode : public HomingMode
      type SW_masks (line 41) | enum SW_masks
      method error (line 47) | bool error(const std::string & msg)
      method DefaultHomingMode (line 55) | DefaultHomingMode(

FILE: canopen_402_driver/include/canopen_402_driver/homing_mode.hpp
  type ros2_canopen (line 23) | namespace ros2_canopen
    class HomingMode (line 25) | class HomingMode : public Mode
      type SW_bits (line 28) | enum SW_bits
      type CW_bits (line 33) | enum CW_bits
      method HomingMode (line 39) | HomingMode() : Mode(MotorBase::Homing) {}

FILE: canopen_402_driver/include/canopen_402_driver/lifecycle_cia402_driver.hpp
  type ros2_canopen (line 23) | namespace ros2_canopen
    class LifecycleCia402Driver (line 31) | class LifecycleCia402Driver : public ros2_canopen::LifecycleCanopenDriver
      method reset_node_nmt_command (line 39) | virtual bool reset_node_nmt_command()
      method start_node_nmt_command (line 44) | virtual bool start_node_nmt_command()
      method tpdo_transmit (line 49) | virtual bool tpdo_transmit(ros2_canopen::COData & data)
      method sdo_write (line 54) | virtual bool sdo_write(ros2_canopen::COData & data)
      method sdo_read (line 59) | virtual bool sdo_read(ros2_canopen::COData & data)
      method register_nmt_state_cb (line 64) | void register_nmt_state_cb(std::function<void(canopen::NmtState, uin...
      method register_rpdo_cb (line 69) | void register_rpdo_cb(std::function<void(COData, uint8_t)> rpdo_cb)
      method get_speed (line 74) | double get_speed() { return node_canopen_402_driver_->get_speed(); }
      method get_position (line 76) | double get_position() { return node_canopen_402_driver_->get_positio...
      method set_target (line 78) | bool set_target(double target) { return node_canopen_402_driver_->se...
      method init_motor (line 80) | bool init_motor() { return node_canopen_402_driver_->init_motor(); }
      method recover_motor (line 82) | bool recover_motor() { return node_canopen_402_driver_->recover_moto...
      method halt_motor (line 84) | bool halt_motor() { return node_canopen_402_driver_->halt_motor(); }
      method get_mode (line 86) | uint16_t get_mode() { return node_canopen_402_driver_->get_mode(); }
      method set_operation_mode (line 88) | bool set_operation_mode(uint16_t mode)

FILE: canopen_402_driver/include/canopen_402_driver/mode.hpp
  type ros2_canopen (line 27) | namespace ros2_canopen
    class Mode (line 29) | class Mode
      method Mode (line 33) | Mode(uint16_t id) : mode_id_(id) {}
      method setTarget (line 42) | virtual bool setTarget(const double & val) { return false; }

FILE: canopen_402_driver/include/canopen_402_driver/mode_forward_helper.hpp
  type ros2_canopen (line 26) | namespace ros2_canopen
    class ModeForwardHelper (line 30) | class ModeForwardHelper : public ModeTargetHelper<TYPE>
      method ModeForwardHelper (line 36) | ModeForwardHelper(std::shared_ptr<LelyDriverBridge> driver, uint16_t...
      method read (line 41) | virtual bool read(const uint16_t & sw) { return true; }
      method write (line 42) | virtual bool write(Mode::OpModeAccesser & cw)

FILE: canopen_402_driver/include/canopen_402_driver/mode_target_helper.hpp
  type ros2_canopen (line 32) | namespace ros2_canopen
    class ModeTargetHelper (line 36) | class ModeTargetHelper : public Mode
      method ModeTargetHelper (line 42) | ModeTargetHelper(uint16_t mode) : Mode(mode) {}
      method hasTarget (line 43) | bool hasTarget() { return has_target_; }
      method T (line 44) | T getTarget() { return target_; }
      method setTarget (line 45) | virtual bool setTarget(const double & val)
      method start (line 83) | virtual bool start()

FILE: canopen_402_driver/include/canopen_402_driver/motor.hpp
  type ros2_canopen (line 38) | namespace ros2_canopen
    class Motor402 (line 59) | class Motor402 : public MotorBase
      method Motor402 (line 62) | Motor402(
      method get_channel_index (line 90) | uint16_t get_channel_index(uint16_t base_index) const { return base_...
      method get_channel (line 92) | uint8_t get_channel() const { return channel_; }
      method registerMode (line 190) | bool registerMode(uint16_t mode, Args &&... args)
      method registerDefaultModes (line 206) | virtual void registerDefaultModes()
      method get_effort (line 225) | double get_effort() const
      method get_speed (line 247) | double get_speed() const
      method get_position (line 252) | double get_position() const
      method set_diagnostic_status_msgs (line 257) | void set_diagnostic_status_msgs(std::shared_ptr<DiagnosticsCollector...

FILE: canopen_402_driver/include/canopen_402_driver/node_interfaces/node_canopen_402_driver.hpp
  type ros2_canopen (line 34) | namespace ros2_canopen
    type node_interfaces (line 36) | namespace node_interfaces
      class NodeCanopen402Driver (line 40) | class NodeCanopen402Driver : public NodeCanopenProxyDriver<NODETYPE>
        type ChannelContext (line 48) | struct ChannelContext
        method get_effort (line 116) | virtual double get_effort(uint8_t channel = 0)
        method get_speed (line 122) | virtual double get_speed(uint8_t channel = 0)
        method get_position (line 128) | virtual double get_position(uint8_t channel = 0)
        method get_mode (line 135) | virtual uint16_t get_mode(uint8_t channel = 0)

FILE: canopen_402_driver/include/canopen_402_driver/profiled_position_mode.hpp
  type ros2_canopen (line 26) | namespace ros2_canopen
    class ProfiledPositionMode (line 28) | class ProfiledPositionMode : public ModeTargetHelper<int32_t>
      type SW_masks (line 38) | enum SW_masks
      type CW_bits (line 44) | enum CW_bits
      method ProfiledPositionMode (line 50) | ProfiledPositionMode(std::shared_ptr<LelyDriverBridge> driver, uint1...
      method start (line 56) | virtual bool start()
      method read (line 62) | virtual bool read(const uint16_t & sw)
      method write (line 67) | virtual bool write(OpModeAccesser & cw)

FILE: canopen_402_driver/include/canopen_402_driver/state.hpp
  type ros2_canopen (line 25) | namespace ros2_canopen
    class State402 (line 27) | class State402
      type StatusWord (line 30) | enum StatusWord
      type InternalState (line 49) | enum InternalState
      method State402 (line 66) | State402() : state_(Unknown) {}

FILE: canopen_402_driver/include/canopen_402_driver/word_accessor.hpp
  type ros2_canopen (line 23) | namespace ros2_canopen
    class WordAccessor (line 26) | class WordAccessor
      method WordAccessor (line 31) | WordAccessor(uint16_t & word) : word_(word) {}
      method set (line 32) | bool set(uint8_t bit)
      method reset (line 38) | bool reset(uint8_t bit)
      method get (line 44) | bool get(uint8_t bit) const { return word_ & (1 << bit); }
      method get (line 45) | uint16_t get() const { return word_ & MASK; }
      method WordAccessor (line 46) | WordAccessor & operator=(const uint16_t & val)

FILE: canopen_402_driver/src/default_homing_mode.cpp
  type masked_status_not_equal (line 21) | struct masked_status_not_equal
    method masked_status_not_equal (line 24) | masked_status_not_equal(uint16_t & status) : status_(status) {}

FILE: canopen_402_driver/src/motor.cpp
  function ModeSharedPtr (line 63) | ModeSharedPtr Motor402::allocMode(uint16_t mode)

FILE: canopen_402_driver/src/node_interfaces/node_canopen_402_driver.cpp
  class ros2_canopen::node_interfaces::NodeCanopen402Driver<rclcpp::Node> (line 23) | class ros2_canopen::node_interfaces::NodeCanopen402Driver<rclcpp::Node>
  class ros2_canopen::node_interfaces::NodeCanopen402Driver<rclcpp_lifecycle::LifecycleNode> (line 24) | class ros2_canopen::node_interfaces::NodeCanopen402Driver<rclcpp_lifecyc...

FILE: canopen_402_driver/test/test_driver_component.cpp
  function TEST (line 25) | TEST(ComponentLoad, test_load_component_1)
  function TEST (line 43) | TEST(ComponentLoad, test_load_component_2)

FILE: canopen_base_driver/include/canopen_base_driver/base_driver.hpp
  type ros2_canopen (line 20) | namespace ros2_canopen
    class BaseDriver (line 28) | class BaseDriver : public ros2_canopen::CanopenDriver
      method register_nmt_state_cb (line 35) | void register_nmt_state_cb(std::function<void(canopen::NmtState, uin...
      method register_rpdo_cb (line 40) | void register_rpdo_cb(std::function<void(COData, uint8_t)> rpdo_cb)

FILE: canopen_base_driver/include/canopen_base_driver/diagnostic_collector.hpp
  type ros2_canopen (line 26) | namespace ros2_canopen
    class DiagnosticsCollector (line 33) | class DiagnosticsCollector
      method DiagnosticsCollector (line 36) | DiagnosticsCollector() : level_(diagnostic_msgs::msg::DiagnosticStat...
      method getLevel (line 43) | unsigned char getLevel() const
      method getMessage (line 53) | std::string getMessage() const { return message_; }
      method getValue (line 62) | std::string getValue(const std::string & key) const
      method summary (line 78) | void summary(unsigned char lvl, const std::string & message)
      method summaryf (line 92) | void summaryf(unsigned char lvl, const char * format, ...)
      method add (line 108) | void add(const std::string & key, const std::string & value)
      method addf (line 121) | void addf(const std::string & key, const char * format, ...)
      method updateAll (line 139) | void updateAll(
      method setLevel (line 155) | void setLevel(unsigned char lvl)
      method setMessage (line 160) | void setMessage(const std::string & message) { message_ = message; }
      method setValue (line 162) | void setValue(const std::string & key, const std::string & value) { ...

FILE: canopen_base_driver/include/canopen_base_driver/lely_driver_bridge.hpp
  type ros2_canopen (line 49) | namespace ros2_canopen
    type pdo_mapping (line 51) | struct pdo_mapping
    class DriverDictionary (line 58) | class DriverDictionary : public lely::CODev
      method DriverDictionary (line 61) | DriverDictionary(std::string eds_file) : lely::CODev(eds_file.c_str(...
      method createPDOMapping (line 67) | std::shared_ptr<PDOMap> createPDOMapping()
      method fetchRPDO (line 111) | void fetchRPDO(std::shared_ptr<PDOMap> map)
      method fetchTPDO (line 141) | void fetchTPDO(std::shared_ptr<PDOMap> map)
      method checkObjRPDO (line 173) | bool checkObjRPDO(uint16_t idx, uint8_t subidx)
      method checkObjTPDO (line 187) | bool checkObjTPDO(uint16_t idx, uint8_t subidx)
      method checkObjInPDO (line 201) | bool checkObjInPDO(uint8_t pdo, uint16_t mapping_idx, uint16_t idx, ...
    type LelyBridgeErrc (line 228) | enum class LelyBridgeErrc
    type LelyBridgeErrCategory (line 248) | struct LelyBridgeErrCategory : std::error_category
    class LelyDriverBridge (line 276) | class LelyDriverBridge : public canopen::FiberDriver
      method OnSync (line 334) | void OnSync(uint8_t cnt, const time_point & t) noexcept override
      method LelyDriverBridge (line 408) | LelyDriverBridge(
      method has_object (line 432) | bool has_object(uint16_t idx, uint8_t subidx)
      method async_sdo_write_typed (line 454) | std::future<bool> async_sdo_write_typed(uint16_t idx, uint8_t subidx...
      method sync_sdo_write_typed (line 500) | bool sync_sdo_write_typed(
      method async_sdo_read_typed (line 540) | std::future<T> async_sdo_read_typed(uint16_t idx, uint8_t subidx)
      method sync_sdo_read_typed (line 592) | bool sync_sdo_read_typed(
      method wait_for_boot (line 685) | bool wait_for_boot()
      method set_sync_function (line 707) | void set_sync_function(std::function<void()> on_sync_function)
      method unset_sync_function (line 712) | void unset_sync_function() { on_sync_function_ = std::function<void(...
      method Boot (line 718) | void Boot()
      method is_booted (line 730) | bool is_booted() { return booted.load(); }
      method submit_write (line 733) | void submit_write(COData data)
      method submit_read (line 761) | void submit_read(COData data)
      method T (line 788) | const T universal_get_value(uint16_t index, uint8_t subindex)
      method universal_set_value (line 839) | void universal_set_value(uint16_t index, uint8_t subindex, T value)
  type std (line 255) | namespace std
    type is_error_code_enum<ros2_canopen::LelyBridgeErrc> (line 258) | struct is_error_code_enum<ros2_canopen::LelyBridgeErrc> : true_type
  type ros2_canopen (line 264) | namespace ros2_canopen
    type pdo_mapping (line 51) | struct pdo_mapping
    class DriverDictionary (line 58) | class DriverDictionary : public lely::CODev
      method DriverDictionary (line 61) | DriverDictionary(std::string eds_file) : lely::CODev(eds_file.c_str(...
      method createPDOMapping (line 67) | std::shared_ptr<PDOMap> createPDOMapping()
      method fetchRPDO (line 111) | void fetchRPDO(std::shared_ptr<PDOMap> map)
      method fetchTPDO (line 141) | void fetchTPDO(std::shared_ptr<PDOMap> map)
      method checkObjRPDO (line 173) | bool checkObjRPDO(uint16_t idx, uint8_t subidx)
      method checkObjTPDO (line 187) | bool checkObjTPDO(uint16_t idx, uint8_t subidx)
      method checkObjInPDO (line 201) | bool checkObjInPDO(uint8_t pdo, uint16_t mapping_idx, uint16_t idx, ...
    type LelyBridgeErrc (line 228) | enum class LelyBridgeErrc
    type LelyBridgeErrCategory (line 248) | struct LelyBridgeErrCategory : std::error_category
    class LelyDriverBridge (line 276) | class LelyDriverBridge : public canopen::FiberDriver
      method OnSync (line 334) | void OnSync(uint8_t cnt, const time_point & t) noexcept override
      method LelyDriverBridge (line 408) | LelyDriverBridge(
      method has_object (line 432) | bool has_object(uint16_t idx, uint8_t subidx)
      method async_sdo_write_typed (line 454) | std::future<bool> async_sdo_write_typed(uint16_t idx, uint8_t subidx...
      method sync_sdo_write_typed (line 500) | bool sync_sdo_write_typed(
      method async_sdo_read_typed (line 540) | std::future<T> async_sdo_read_typed(uint16_t idx, uint8_t subidx)
      method sync_sdo_read_typed (line 592) | bool sync_sdo_read_typed(
      method wait_for_boot (line 685) | bool wait_for_boot()
      method set_sync_function (line 707) | void set_sync_function(std::function<void()> on_sync_function)
      method unset_sync_function (line 712) | void unset_sync_function() { on_sync_function_ = std::function<void(...
      method Boot (line 718) | void Boot()
      method is_booted (line 730) | bool is_booted() { return booted.load(); }
      method submit_write (line 733) | void submit_write(COData data)
      method submit_read (line 761) | void submit_read(COData data)
      method T (line 788) | const T universal_get_value(uint16_t index, uint8_t subindex)
      method universal_set_value (line 839) | void universal_set_value(uint16_t index, uint8_t subindex, T value)

FILE: canopen_base_driver/include/canopen_base_driver/lifecycle_base_driver.hpp
  type ros2_canopen (line 20) | namespace ros2_canopen
    class LifecycleBaseDriver (line 28) | class LifecycleBaseDriver : public ros2_canopen::LifecycleCanopenDriver
      method register_nmt_state_cb (line 36) | void register_nmt_state_cb(std::function<void(canopen::NmtState, uin...
      method register_rpdo_cb (line 41) | void register_rpdo_cb(std::function<void(COData, uint8_t)> rpdo_cb)

FILE: canopen_base_driver/include/canopen_base_driver/node_interfaces/node_canopen_base_driver.hpp
  type ros2_canopen (line 28) | namespace ros2_canopen
    type node_interfaces (line 30) | namespace node_interfaces
      class NodeCanopenBaseDriver (line 33) | class NodeCanopenBaseDriver : public NodeCanopenDriver<NODETYPE>
        method register_nmt_state_cb (line 113) | void register_nmt_state_cb(std::function<void(canopen::NmtState, u...
        method register_rpdo_cb (line 123) | void register_rpdo_cb(std::function<void(COData, uint8_t)> rpdo_cb)
        method register_emcy_cb (line 133) | void register_emcy_cb(std::function<void(COEmcy, uint8_t)> emcy_cb)

FILE: canopen_base_driver/src/lely_driver_bridge.cpp
  type ros2_canopen (line 26) | namespace ros2_canopen

FILE: canopen_base_driver/src/node_interfaces/node_canopen_base_driver.cpp
  class ros2_canopen::node_interfaces::NodeCanopenBaseDriver<rclcpp::Node> (line 21) | class ros2_canopen::node_interfaces::NodeCanopenBaseDriver<rclcpp::Node>
  class ros2_canopen::node_interfaces::NodeCanopenBaseDriver<
  rclcpp_lifecycle::LifecycleNode> (line 22) | class ros2_canopen::node_interfaces::NodeCanopenBaseDriver<

FILE: canopen_base_driver/test/test_base_driver_component.cpp
  function TEST (line 24) | TEST(ComponentLoad, test_load_component_1)
  function TEST (line 42) | TEST(ComponentLoad, test_load_component_2)

FILE: canopen_base_driver/test/test_node_canopen_base_driver_ros.cpp
  function TEST (line 20) | TEST(NodeCanopenBaseDriver, test_good_sequence_advanced)
  function TEST (line 56) | TEST(NodeCanopenBasicLifecycleMaster, test_good_sequence_advanced)

FILE: canopen_core/include/canopen_core/configuration_manager.hpp
  type ros2_canopen (line 27) | namespace ros2_canopen
    class ConfigurationManager (line 38) | class ConfigurationManager
      method ConfigurationManager (line 46) | ConfigurationManager(std::string & file) : file_(file) { root_ = YAM...
      method get_entry (line 57) | std::optional<T> get_entry(std::string device_name, std::string entr...
      method dump_device (line 80) | std::string dump_device(std::string device_name)

FILE: canopen_core/include/canopen_core/device_container.hpp
  type ros2_canopen (line 33) | namespace ros2_canopen
    class DeviceContainer (line 44) | class DeviceContainer : public rclcpp_components::ComponentManager
      method DeviceContainer (line 54) | DeviceContainer(
      method shutdown (line 152) | virtual void shutdown()
      method get_registered_drivers (line 194) | virtual std::map<uint16_t, std::shared_ptr<CanopenDriverInterface>> ...
      method count_drivers (line 204) | virtual size_t count_drivers() { return registered_drivers_.size(); }
      method get_ids_of_drivers_with_type (line 216) | std::vector<uint16_t> get_ids_of_drivers_with_type(std::string type)
      method get_driver_type (line 250) | std::string get_driver_type(uint16_t id)
      method on_init_driver (line 320) | void on_init_driver(
      method add_node_to_executor (line 339) | virtual void add_node_to_executor(

FILE: canopen_core/include/canopen_core/device_container_error.hpp
  type ros2_canopen (line 21) | namespace ros2_canopen
    class DeviceContainerException (line 31) | class DeviceContainerException : public std::exception
      method DeviceContainerException (line 37) | DeviceContainerException(std::string what) { what_ = what; }

FILE: canopen_core/include/canopen_core/driver_error.hpp
  type ros2_canopen (line 21) | namespace ros2_canopen
    class DriverException (line 30) | class DriverException : public std::exception
      method DriverException (line 36) | DriverException(std::string what) { what_ = what; }

FILE: canopen_core/include/canopen_core/driver_node.hpp
  type ros2_canopen (line 21) | namespace ros2_canopen
    class CanopenDriverInterface (line 30) | class CanopenDriverInterface
    class CanopenDriver (line 104) | class CanopenDriver : public CanopenDriverInterface, public rclcpp::Node
      method CanopenDriver (line 108) | explicit CanopenDriver(const rclcpp::NodeOptions & node_options = rc...
      method get_node_base_interface (line 147) | virtual rclcpp::node_interfaces::NodeBaseInterface::SharedPtr get_no...
      method is_lifecycle (line 166) | virtual bool is_lifecycle() override { return false; }
      method get_node_canopen_driver_interface (line 175) | virtual std::shared_ptr<node_interfaces::NodeCanopenDriverInterface>
    class LifecycleCanopenDriver (line 189) | class LifecycleCanopenDriver : public CanopenDriverInterface, public r...
      method LifecycleCanopenDriver (line 195) | explicit LifecycleCanopenDriver(const rclcpp::NodeOptions & node_opt...
      method get_node_base_interface (line 293) | rclcpp::node_interfaces::NodeBaseInterface::SharedPtr get_node_base_...
      method is_lifecycle (line 311) | virtual bool is_lifecycle() override { return true; }
      method get_node_canopen_driver_interface (line 319) | virtual std::shared_ptr<node_interfaces::NodeCanopenDriverInterface>

FILE: canopen_core/include/canopen_core/exchange.hpp
  type ros2_canopen (line 22) | namespace ros2_canopen
    type COData (line 25) | struct COData
    type COEmcy (line 33) | struct COEmcy
    class SafeQueue (line 48) | class SafeQueue
      method SafeQueue (line 59) | explicit SafeQueue(std::size_t capacity = 10)
      method push (line 68) | void push(T value) { queue_->push(std::move(value)); }
      method try_pop (line 74) | std::optional<T> try_pop()
      method try_pop (line 85) | bool try_pop(T & value)
      method wait_and_pop (line 95) | boost::optional<T> wait_and_pop()
      method wait_and_pop (line 106) | void wait_and_pop(T & value)
      method wait_and_pop_for (line 116) | boost::optional<T> wait_and_pop_for(const std::chrono::milliseconds ...
      method wait_and_pop_for (line 136) | bool wait_and_pop_for(const std::chrono::milliseconds & timeout, T &...
      method empty (line 150) | bool empty() const { return queue_->empty(); }

FILE: canopen_core/include/canopen_core/lifecycle_manager.hpp
  type ros2_canopen (line 39) | namespace ros2_canopen
    class LifecycleManager (line 65) | class LifecycleManager : public rclcpp_lifecycle::LifecycleNode
      method LifecycleManager (line 73) | LifecycleManager(const rclcpp::NodeOptions & node_options)
      method wait_for_result (line 164) | std::future_status wait_for_result(FutureT & future, WaitTimeT time_...

FILE: canopen_core/include/canopen_core/master_error.hpp
  type ros2_canopen (line 20) | namespace ros2_canopen
    class MasterException (line 29) | class MasterException : public std::exception
      method MasterException (line 35) | MasterException(std::string what) { what_ = what; }

FILE: canopen_core/include/canopen_core/master_node.hpp
  type ros2_canopen (line 20) | namespace ros2_canopen
    class CanopenMasterInterface (line 28) | class CanopenMasterInterface
    class CanopenMaster (line 97) | class CanopenMaster : public CanopenMasterInterface, public rclcpp::Node
      method CanopenMaster (line 101) | explicit CanopenMaster(const rclcpp::NodeOptions & node_options = rc...
      method get_node_base_interface (line 159) | virtual rclcpp::node_interfaces::NodeBaseInterface::SharedPtr get_no...
      method is_lifecycle (line 168) | virtual bool is_lifecycle() { return false; }
    class LifecycleCanopenMaster (line 171) | class LifecycleCanopenMaster : public CanopenMasterInterface, public r...
      method LifecycleCanopenMaster (line 177) | LifecycleCanopenMaster(const rclcpp::NodeOptions & node_options = rc...
      method get_node_base_interface (line 289) | virtual rclcpp::node_interfaces::NodeBaseInterface::SharedPtr get_no...
      method is_lifecycle (line 298) | virtual bool is_lifecycle() { return true; }

FILE: canopen_core/include/canopen_core/node_interfaces/node_canopen_driver.hpp
  type ros2_canopen (line 43) | namespace ros2_canopen
    type node_interfaces (line 45) | namespace node_interfaces
      class NodeCanopenDriver (line 59) | class NodeCanopenDriver : public NodeCanopenDriverInterface
        method NodeCanopenDriver (line 89) | NodeCanopenDriver(NODETYPE * node)
        method set_master (line 102) | virtual void set_master(
        method init (line 127) | void init()
        method init (line 162) | virtual void init(bool called_from_base) {}
        method configure (line 175) | void configure()
        method configure (line 214) | virtual void configure(bool called_from_base) {}
        method activate (line 223) | void activate()
        method activate (line 256) | virtual void activate(bool called_from_base) {}
        method deactivate (line 265) | void deactivate()
        method deactivate (line 296) | virtual void deactivate(bool called_from_base) {}
        method cleanup (line 305) | void cleanup()
        method cleanup (line 330) | virtual void cleanup(bool called_from_base)
        method shutdown (line 344) | void shutdown()
        method shutdown (line 368) | virtual void shutdown(bool called_from_base) {}
        method add_to_master (line 377) | virtual void add_to_master() { throw DriverException("Add to maste...
        method remove_from_master (line 383) | virtual void remove_from_master()

FILE: canopen_core/include/canopen_core/node_interfaces/node_canopen_driver_interface.hpp
  type ros2_canopen (line 21) | namespace ros2_canopen
    type node_interfaces (line 23) | namespace node_interfaces
      class NodeCanopenDriverInterface (line 32) | class NodeCanopenDriverInterface
        method NodeCanopenDriverInterface (line 35) | NodeCanopenDriverInterface() {}

FILE: canopen_core/include/canopen_core/node_interfaces/node_canopen_master.hpp
  type ros2_canopen (line 35) | namespace ros2_canopen
    type node_interfaces (line 37) | namespace node_interfaces
      class NodeCanopenMaster (line 51) | class NodeCanopenMaster : public NodeCanopenMasterInterface
        method NodeCanopenMaster (line 93) | NodeCanopenMaster(NODETYPE * node)
        method init (line 103) | void init() override
        method init (line 128) | virtual void init(bool called_from_base) {}
        method configure (line 137) | void configure() override
        method configure (line 170) | virtual void configure(bool called_from_base)
        method activate (line 195) | void activate() override
        method activate (line 254) | virtual void activate(bool called_from_base) {}
        method deactivate (line 263) | void deactivate() override
        method deactivate (line 297) | virtual void deactivate(bool called_from_base) {}
        method cleanup (line 306) | void cleanup() override
        method cleanup (line 333) | virtual void cleanup(bool called_from_base) {}
        method shutdown (line 341) | void shutdown() override
        method shutdown (line 360) | virtual void shutdown(bool called_from_base) {}
        method get_master (line 367) | virtual std::shared_ptr<lely::canopen::AsyncMaster> get_master()
        method get_executor (line 380) | virtual std::shared_ptr<lely::ev::Executor> get_executor()

FILE: canopen_core/include/canopen_core/node_interfaces/node_canopen_master_interface.hpp
  type ros2_canopen (line 22) | namespace ros2_canopen
    type node_interfaces (line 24) | namespace node_interfaces
      class NodeCanopenMasterInterface (line 33) | class NodeCanopenMasterInterface

FILE: canopen_core/launch/canopen.launch.py
  function generate_launch_description (line 33) | def generate_launch_description():

FILE: canopen_core/src/configuration_manager.cpp
  type ros2_canopen (line 18) | namespace ros2_canopen

FILE: canopen_core/src/device_container_error.cpp
  type ros2_canopen (line 17) | namespace ros2_canopen

FILE: canopen_core/src/device_container_node.cpp
  function main (line 20) | int main(int argc, char const * argv[])

FILE: canopen_core/src/driver_error.cpp
  type ros2_canopen (line 17) | namespace ros2_canopen

FILE: canopen_core/src/lifecycle_manager.cpp
  type ros2_canopen (line 17) | namespace ros2_canopen

FILE: canopen_core/src/master_error.cpp
  type ros2_canopen (line 17) | namespace ros2_canopen

FILE: canopen_core/src/node_interfaces/node_canopen_driver.cpp
  class ros2_canopen::node_interfaces::NodeCanopenDriver<rclcpp::Node> (line 103) | class ros2_canopen::node_interfaces::NodeCanopenDriver<rclcpp::Node>
  class ros2_canopen::node_interfaces::NodeCanopenDriver<rclcpp_lifecycle::LifecycleNode> (line 104) | class ros2_canopen::node_interfaces::NodeCanopenDriver<rclcpp_lifecycle:...

FILE: canopen_core/src/node_interfaces/node_canopen_master.cpp
  class ros2_canopen::node_interfaces::NodeCanopenMaster<rclcpp::Node> (line 17) | class ros2_canopen::node_interfaces::NodeCanopenMaster<rclcpp::Node>
  class ros2_canopen::node_interfaces::NodeCanopenMaster<rclcpp_lifecycle::LifecycleNode> (line 18) | class ros2_canopen::node_interfaces::NodeCanopenMaster<rclcpp_lifecycle:...

FILE: canopen_core/test/test_canopen_driver.cpp
  class MockNodeCanopenMaster (line 23) | class MockNodeCanopenMaster : public ros2_canopen::node_interfaces::Node...
  class MockCanopenMaster (line 41) | class MockCanopenMaster : public CanopenDriver
  class CanopenDriverTest (line 47) | class CanopenDriverTest : public testing::Test
    method SetUp (line 52) | void SetUp() override
    method TearDown (line 63) | void TearDown() override
  function TEST_F (line 70) | TEST_F(CanopenDriverTest, test_init)
  function TEST_F (line 79) | TEST_F(CanopenDriverTest, test_set_master)
  function TEST_F (line 88) | TEST_F(CanopenDriverTest, test_get_node_base_interface)
  function TEST_F (line 94) | TEST_F(CanopenDriverTest, test_shutdown)
  function TEST_F (line 100) | TEST_F(CanopenDriverTest, test_is_lifecycle) { EXPECT_FALSE(canopen_driv...
  function TEST_F (line 102) | TEST_F(CanopenDriverTest, test_get_node_canopen_driver_interface)

FILE: canopen_core/test/test_canopen_master.cpp
  class MockNodeCanopenMaster (line 23) | class MockNodeCanopenMaster : public ros2_canopen::node_interfaces::Node...
  class MockCanopenMaster (line 36) | class MockCanopenMaster : public CanopenMaster
  class CanopenMasterTest (line 42) | class CanopenMasterTest : public testing::Test
    method SetUp (line 47) | void SetUp() override
    method TearDown (line 58) | void TearDown() override
  function TEST_F (line 65) | TEST_F(CanopenMasterTest, test_init)
  function TEST_F (line 73) | TEST_F(CanopenMasterTest, test_get_node_base_interface)
  function TEST_F (line 79) | TEST_F(CanopenMasterTest, test_shutdown)
  function TEST_F (line 85) | TEST_F(CanopenMasterTest, test_is_lifecycle) { EXPECT_FALSE(canopen_mast...
  function TEST_F (line 87) | TEST_F(CanopenMasterTest, test_get_master)
  function TEST_F (line 93) | TEST_F(CanopenMasterTest, test_get_executor)

FILE: canopen_core/test/test_device_container.cpp
  class MockNodeFactory (line 24) | class MockNodeFactory : public rclcpp_components::NodeFactory
  class FakeDeviceContainer (line 32) | class FakeDeviceContainer
    method get_component_resources (line 35) | virtual std::vector<rclcpp_components::ComponentManager::ComponentReso...
  class MockDeviceContainer (line 55) | class MockDeviceContainer : public DeviceContainer
    method MockDeviceContainer (line 82) | MockDeviceContainer(
    method DelegateToFake (line 107) | void DelegateToFake()
  class MockCanopenDriver (line 135) | class MockCanopenDriver : public CanopenDriverInterface, public rclcpp::...
    method MockCanopenDriver (line 138) | explicit MockCanopenDriver(
    method get_node_base_interface (line 151) | rclcpp::node_interfaces::NodeBaseInterface::SharedPtr get_node_base_in...
  class MockCanopenMaster (line 162) | class MockCanopenMaster : public CanopenMasterInterface, public rclcpp::...
    method MockCanopenMaster (line 165) | explicit MockCanopenMaster(
    method get_node_base_interface (line 175) | rclcpp::node_interfaces::NodeBaseInterface::SharedPtr get_node_base_in...
  class DeviceContainerTest (line 182) | class DeviceContainerTest : public testing::Test
    method SetUp (line 188) | void SetUp() override
    method TearDown (line 200) | void TearDown() override
  function TEST_F (line 212) | TEST_F(DeviceContainerTest, test_name_and_parameters_declared)
  function TEST_F (line 221) | TEST_F(DeviceContainerTest, test_services_declared)
  function TEST_F (line 248) | TEST_F(DeviceContainerTest, test_load_component_master)
  function TEST_F (line 274) | TEST_F(DeviceContainerTest, test_load_component_driver_non_lifecycle)
  function TEST_F (line 318) | TEST_F(DeviceContainerTest, test_load_component_driver_lifecycle)
  function TEST_F (line 362) | TEST_F(DeviceContainerTest, test_get_registered_drivers)
  function TEST_F (line 404) | TEST_F(DeviceContainerTest, test_count_drivers)
  function TEST_F (line 444) | TEST_F(DeviceContainerTest, test_shutdown)
  function TEST_F (line 505) | TEST_F(DeviceContainerTest, test_get_ids_of_drivers_with_type)
  function TEST_F (line 515) | TEST_F(DeviceContainerTest, test_get_driver_type)
  function TEST_F (line 525) | TEST_F(DeviceContainerTest, test_on_list_nodes)
  function TEST_F (line 599) | TEST_F(DeviceContainerTest, test_load_master_good)
  function TEST_F (line 623) | TEST_F(DeviceContainerTest, test_load_master_load_component_fail)
  function TEST_F (line 635) | TEST_F(DeviceContainerTest, test_load_master_bad_no_driver)
  function TEST_F (line 646) | TEST_F(DeviceContainerTest, test_load_master_bad_no_id)
  function TEST_F (line 657) | TEST_F(DeviceContainerTest, test_load_master_bad_no_package)
  function TEST_F (line 668) | TEST_F(DeviceContainerTest, test_load_driver_good)
  function TEST_F (line 691) | TEST_F(DeviceContainerTest, test_load_driver_load_component_fail)
  function TEST_F (line 703) | TEST_F(DeviceContainerTest, test_load_driver_bad_no_id)
  function TEST_F (line 713) | TEST_F(DeviceContainerTest, test_load_driver_bad_no_driver)
  function TEST_F (line 723) | TEST_F(DeviceContainerTest, test_load_driver_bad_no_package)
  function TEST_F (line 733) | TEST_F(DeviceContainerTest, test_load_manager_no_lifecycle)
  function TEST_F (line 741) | TEST_F(DeviceContainerTest, test_load_manager_lifecycle)
  function TEST_F (line 750) | TEST_F(DeviceContainerTest, test_configure_good)
  function TEST_F (line 761) | TEST_F(DeviceContainerTest, test_init)
  function TEST_F (line 775) | TEST_F(DeviceContainerTest, test_init_with_fparam)

FILE: canopen_core/test/test_errors.cpp
  function TEST (line 25) | TEST(DriverErrorTest, test_what)
  function TEST (line 31) | TEST(MasterErrorTest, test_what)
  function TEST (line 37) | TEST(DeviceContainerErrorTest, test_what)

FILE: canopen_core/test/test_lifecycle_canopen_driver.cpp
  class MockNodeCanopenMaster (line 23) | class MockNodeCanopenMaster : public ros2_canopen::node_interfaces::Node...
  class MockCanopenMaster (line 41) | class MockCanopenMaster : public LifecycleCanopenDriver
  class CanopenDriverTest (line 47) | class CanopenDriverTest : public testing::Test
    method SetUp (line 52) | void SetUp() override
    method TearDown (line 63) | void TearDown() override
  function TEST_F (line 70) | TEST_F(CanopenDriverTest, test_init)
  function TEST_F (line 76) | TEST_F(CanopenDriverTest, test_set_master)
  function TEST_F (line 85) | TEST_F(CanopenDriverTest, test_get_node_base_interface)
  function TEST_F (line 91) | TEST_F(CanopenDriverTest, test_shutdown)
  function TEST_F (line 97) | TEST_F(CanopenDriverTest, test_is_lifecycle) { EXPECT_TRUE(canopen_drive...
  function TEST_F (line 99) | TEST_F(CanopenDriverTest, test_get_node_canopen_driver_interface)
  function TEST_F (line 104) | TEST_F(CanopenDriverTest, test_on_configure)
  function TEST_F (line 112) | TEST_F(CanopenDriverTest, test_on_activate)
  function TEST_F (line 119) | TEST_F(CanopenDriverTest, test_on_deactivate)
  function TEST_F (line 126) | TEST_F(CanopenDriverTest, test_on_cleanup)
  function TEST_F (line 133) | TEST_F(CanopenDriverTest, test_on_shutdown)

FILE: canopen_core/test/test_lifecycle_canopen_master.cpp
  class MockNodeCanopenMaster (line 23) | class MockNodeCanopenMaster : public ros2_canopen::node_interfaces::Node...
  class MockCanopenMaster (line 36) | class MockCanopenMaster : public LifecycleCanopenMaster
  class CanopenMasterTest (line 42) | class CanopenMasterTest : public testing::Test
    method SetUp (line 47) | void SetUp() override
    method TearDown (line 58) | void TearDown() override
  function TEST_F (line 65) | TEST_F(CanopenMasterTest, test_init)
  function TEST_F (line 71) | TEST_F(CanopenMasterTest, test_get_node_base_interface)
  function TEST_F (line 77) | TEST_F(CanopenMasterTest, test_shutdown)
  function TEST_F (line 83) | TEST_F(CanopenMasterTest, test_is_lifecycle) { EXPECT_TRUE(canopen_maste...
  function TEST_F (line 85) | TEST_F(CanopenMasterTest, test_get_master)
  function TEST_F (line 91) | TEST_F(CanopenMasterTest, test_get_executor)
  function TEST_F (line 97) | TEST_F(CanopenMasterTest, test_on_configure)
  function TEST_F (line 104) | TEST_F(CanopenMasterTest, test_on_activate)
  function TEST_F (line 111) | TEST_F(CanopenMasterTest, test_on_deactivate)
  function TEST_F (line 118) | TEST_F(CanopenMasterTest, test_on_cleanup)
  function TEST_F (line 125) | TEST_F(CanopenMasterTest, test_on_shutdown)

FILE: canopen_core/test/test_lifecycle_manager.cpp
  class MockLifecycleManager (line 23) | class MockLifecycleManager : public LifecycleManager
    method MockLifecycleManager (line 56) | MockLifecycleManager() : LifecycleManager(rclcpp::NodeOptions()) {}
    method DelegateToBase (line 68) | void DelegateToBase()
  class LifecycleManagerTest (line 99) | class LifecycleManagerTest : public testing::Test
    method SetUp (line 103) | void SetUp() override
    method TearDown (line 111) | void TearDown() override
    method SetUpConfigurationManager (line 117) | void SetUpConfigurationManager()
  function TEST_F (line 128) | TEST_F(LifecycleManagerTest, test_constructor)
  function TEST_F (line 134) | TEST_F(LifecycleManagerTest, test_init)
  function TEST_F (line 143) | TEST_F(LifecycleManagerTest, test_bring_up_master)
  function TEST_F (line 151) | TEST_F(LifecycleManagerTest, test_bring_up_master_false_initial_state)
  function TEST_F (line 158) | TEST_F(LifecycleManagerTest, test_bring_up_master_failed_configure)
  function TEST_F (line 166) | TEST_F(LifecycleManagerTest, test_bring_up_master_failed_activate)
  function TEST_F (line 177) | TEST_F(LifecycleManagerTest, test_bring_down_master)
  function TEST_F (line 187) | TEST_F(LifecycleManagerTest, test_bring_down_master_false_state)
  function TEST_F (line 197) | TEST_F(LifecycleManagerTest, test_bring_up_driver)
  function TEST_F (line 209) | TEST_F(LifecycleManagerTest, test_bring_up_driver_false_state_master)
  function TEST_F (line 220) | TEST_F(LifecycleManagerTest, test_bring_up_driver_false_state_driver)
  function TEST_F (line 232) | TEST_F(LifecycleManagerTest, test_bring_up_driver_fail_configure)
  function TEST_F (line 245) | TEST_F(LifecycleManagerTest, test_bring_up_driver_fail_activate)
  function TEST_F (line 261) | TEST_F(LifecycleManagerTest, test_bring_down_driver)
  function TEST_F (line 276) | TEST_F(LifecycleManagerTest, test_bring_down_driver_failed)
  function TEST_F (line 291) | TEST_F(LifecycleManagerTest, test_bring_up_all)
  function TEST_F (line 301) | TEST_F(LifecycleManagerTest, test_bring_up_all_fail_master)
  function TEST_F (line 310) | TEST_F(LifecycleManagerTest, test_bring_up_all_fail_driver)
  function TEST_F (line 320) | TEST_F(LifecycleManagerTest, test_bring_down_all)
  function TEST_F (line 329) | TEST_F(LifecycleManagerTest, test_bring_down_all_fail_driver)
  function TEST_F (line 337) | TEST_F(LifecycleManagerTest, test_bring_down_all_fail_master)
  function TEST_F (line 346) | TEST_F(LifecycleManagerTest, test_on_configure)
  function TEST_F (line 355) | TEST_F(LifecycleManagerTest, test_on_configure_fail)
  function TEST_F (line 364) | TEST_F(LifecycleManagerTest, test_on_activate)
  function TEST_F (line 373) | TEST_F(LifecycleManagerTest, test_on_activate_fail)
  function TEST_F (line 382) | TEST_F(LifecycleManagerTest, test_on_deactivate)
  function TEST_F (line 391) | TEST_F(LifecycleManagerTest, test_on_deactivate_fail)
  function TEST_F (line 400) | TEST_F(LifecycleManagerTest, test_on_cleanup)
  function TEST_F (line 408) | TEST_F(LifecycleManagerTest, test_on_shutdown)

FILE: canopen_core/test/test_node_canopen_driver.cpp
  class MockNodeCanopenDriver (line 24) | class MockNodeCanopenDriver : public NodeCanopenDriver<NODETYPE>
    method MockNodeCanopenDriver (line 44) | MockNodeCanopenDriver(rclcpp::Node * node) : NodeCanopenDriver<NODETYP...
    method DelegateToBase (line 48) | void DelegateToBase()
  class NodeCanopenDriverTest (line 60) | class NodeCanopenDriverTest : public testing::Test
    method SetUp (line 65) | void SetUp() override
    method TearDown (line 74) | void TearDown() override
  function TEST_F (line 81) | TEST_F(NodeCanopenDriverTest, test_construct) { EXPECT_EQ(node.get(), no...
  function TEST_F (line 83) | TEST_F(NodeCanopenDriverTest, test_init)
  function TEST_F (line 95) | TEST_F(NodeCanopenDriverTest, test_init_fail_configured)
  function TEST_F (line 107) | TEST_F(NodeCanopenDriverTest, test_init_fail_activated)
  function TEST_F (line 119) | TEST_F(NodeCanopenDriverTest, test_set_master)
  function TEST_F (line 140) | TEST_F(NodeCanopenDriverTest, test_configure)
  function TEST_F (line 154) | TEST_F(NodeCanopenDriverTest, test_configure_fail_not_initialsed)
  function TEST_F (line 162) | TEST_F(NodeCanopenDriverTest, test_configure_fail_configured)
  function TEST_F (line 173) | TEST_F(NodeCanopenDriverTest, test_configure_fail_activated)
  function TEST_F (line 185) | TEST_F(NodeCanopenDriverTest, test_activate)
  function TEST_F (line 196) | TEST_F(NodeCanopenDriverTest, test_activate_failures)
  function TEST_F (line 220) | TEST_F(NodeCanopenDriverTest, test_deactivate)
  function TEST_F (line 231) | TEST_F(NodeCanopenDriverTest, test_deactivate_failures)
  function TEST_F (line 255) | TEST_F(NodeCanopenDriverTest, test_cleanup)
  function TEST_F (line 264) | TEST_F(NodeCanopenDriverTest, test_cleanup_failures)
  function TEST_F (line 280) | TEST_F(NodeCanopenDriverTest, test_shutdown)

FILE: canopen_core/test/test_node_canopen_master.cpp
  class MockNodeCanopenMaster (line 24) | class MockNodeCanopenMaster : public NodeCanopenMaster<NODETYPE>
    method MockNodeCanopenMaster (line 65) | MockNodeCanopenMaster(NODETYPE * node) : NodeCanopenMaster<NODETYPE>(n...
    method DelegateToBase (line 67) | void DelegateToBase()
  class NodeCanopenMasterTest (line 79) | class NodeCanopenMasterTest : public testing::Test
    method SetUp (line 84) | void SetUp() override
    method TearDown (line 93) | void TearDown() override
  function TEST_F (line 100) | TEST_F(NodeCanopenMasterTest, test_construct) { EXPECT_EQ(node.get(), no...
  function TEST_F (line 102) | TEST_F(NodeCanopenMasterTest, test_init)
  function TEST_F (line 114) | TEST_F(NodeCanopenMasterTest, test_init_fail_configured)
  function TEST_F (line 126) | TEST_F(NodeCanopenMasterTest, test_init_fail_activated)
  function TEST_F (line 138) | TEST_F(NodeCanopenMasterTest, test_configure)
  function TEST_F (line 149) | TEST_F(NodeCanopenMasterTest, test_configure_fail_not_initialsed)
  function TEST_F (line 157) | TEST_F(NodeCanopenMasterTest, test_configure_fail_configured)
  function TEST_F (line 168) | TEST_F(NodeCanopenMasterTest, test_configure_fail_activated)
  function TEST_F (line 180) | TEST_F(NodeCanopenMasterTest, test_activate_failures)
  function TEST_F (line 196) | TEST_F(NodeCanopenMasterTest, test_deactivate_failures)
  function TEST_F (line 212) | TEST_F(NodeCanopenMasterTest, test_cleanup)
  function TEST_F (line 221) | TEST_F(NodeCanopenMasterTest, test_cleanup_failures)
  function TEST_F (line 237) | TEST_F(NodeCanopenMasterTest, test_shutdown)
  function TEST_F (line 250) | TEST_F(NodeCanopenMasterTest, test_get_master)
  function TEST_F (line 259) | TEST_F(NodeCanopenMasterTest, test_get_executor)
  class NodeCanopenLMasterTest (line 268) | class NodeCanopenLMasterTest : public testing::Test
    method SetUp (line 273) | void SetUp() override
    method TearDown (line 283) | void TearDown() override
  function TEST_F (line 290) | TEST_F(NodeCanopenLMasterTest, test_construct)
  function TEST_F (line 295) | TEST_F(NodeCanopenLMasterTest, test_init)
  function TEST_F (line 307) | TEST_F(NodeCanopenLMasterTest, test_init_fail_configured)
  function TEST_F (line 319) | TEST_F(NodeCanopenLMasterTest, test_init_fail_activated)
  function TEST_F (line 331) | TEST_F(NodeCanopenLMasterTest, test_configure)
  function TEST_F (line 342) | TEST_F(NodeCanopenLMasterTest, test_configure_fail_not_initialsed)
  function TEST_F (line 350) | TEST_F(NodeCanopenLMasterTest, test_configure_fail_configured)
  function TEST_F (line 361) | TEST_F(NodeCanopenLMasterTest, test_configure_fail_activated)
  function TEST_F (line 373) | TEST_F(NodeCanopenLMasterTest, test_activate_failures)
  function TEST_F (line 389) | TEST_F(NodeCanopenLMasterTest, test_deactivate_failures)
  function TEST_F (line 405) | TEST_F(NodeCanopenLMasterTest, test_cleanup)
  function TEST_F (line 414) | TEST_F(NodeCanopenLMasterTest, test_cleanup_failures)
  function TEST_F (line 430) | TEST_F(NodeCanopenLMasterTest, test_shutdown)
  function TEST_F (line 443) | TEST_F(NodeCanopenLMasterTest, test_get_master)
  function TEST_F (line 452) | TEST_F(NodeCanopenLMasterTest, test_get_executor)

FILE: canopen_fake_slaves/include/canopen_fake_slaves/base_slave.hpp
  type ros2_canopen (line 20) | namespace ros2_canopen
    class BaseSlave (line 22) | class BaseSlave : public rclcpp_lifecycle::LifecycleNode
      method BaseSlave (line 25) | explicit BaseSlave(const std::string & node_name, bool intra_process...
      method on_configure (line 52) | rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackR...
      method on_activate (line 60) | rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackR...
      method on_deactivate (line 72) | rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackR...
      method on_cleanup (line 84) | rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackR...
      method on_shutdown (line 92) | rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackR...

FILE: canopen_fake_slaves/include/canopen_fake_slaves/basic_slave.hpp
  type ros2_canopen (line 38) | namespace ros2_canopen
    class SimpleSlave (line 40) | class SimpleSlave : public canopen::BasicSlave
      method SimpleSlave (line 43) | SimpleSlave(
      method SimpleSlave (line 68) | SimpleSlave(
      method parse_vendor_id (line 85) | static uint32_t parse_vendor_id(const std::string & slave_config)
      method GetValue (line 122) | uint32_t GetValue(const uint16_t idx, const uint8_t subidx) const no...
      method OnWrite (line 174) | void OnWrite(uint16_t idx, uint8_t subidx) noexcept override
      method fake_periodic_messages (line 190) | void fake_periodic_messages()
    class BasicSlave (line 204) | class BasicSlave : public BaseSlave
      method BasicSlave (line 207) | explicit BasicSlave(const std::string & node_name, bool intra_proces...
      class ActiveCheckTask (line 213) | class ActiveCheckTask : public ev::CoTask
        method ActiveCheckTask (line 216) | ActiveCheckTask(io::Context * ctx, ev::Executor * exec, BasicSlave...
      method run (line 236) | void run() override

FILE: canopen_fake_slaves/include/canopen_fake_slaves/cia402_slave.hpp
  type ros2_canopen (line 37) | namespace ros2_canopen
    class CIA402MockSlave (line 40) | class CIA402MockSlave : public canopen::BasicSlave
      method CIA402MockSlave (line 43) | explicit CIA402MockSlave(
      type InternalState (line 85) | enum InternalState
      type StatusWord (line 99) | enum StatusWord
      type ControlWord (line 118) | enum ControlWord
      type OperationMode (line 138) | enum OperationMode
      type CiaRegister (line 153) | enum CiaRegister : uint16_t
      method run_profiled_position_mode (line 198) | void run_profiled_position_mode()
      method run_cyclic_position_mode (line 261) | void run_cyclic_position_mode()
      method run_interpolated_position_mode (line 310) | void run_interpolated_position_mode()
      method run_profile_velocity_mode (line 375) | void run_profile_velocity_mode()
      method run_homing_mode (line 405) | void run_homing_mode()
      method set_new_status_word_and_state (line 442) | void set_new_status_word_and_state()
      method set_status_bit (line 474) | void set_status_bit(int bit)
      method clear_status_bit (line 480) | void clear_status_bit(int bit)
      method set_switch_on_disabled (line 486) | void set_switch_on_disabled()
      method set_ready_to_switch_on (line 497) | void set_ready_to_switch_on()
      method set_switch_on (line 509) | void set_switch_on()
      method set_operation_enabled (line 521) | void set_operation_enabled()
      method set_quick_stop (line 533) | void set_quick_stop()
      method on_not_ready_to_switch_on (line 545) | void on_not_ready_to_switch_on() { set_switch_on_disabled(); }
      method on_switch_on_disabled (line 547) | void on_switch_on_disabled()
      method on_ready_to_switch_on (line 555) | void on_ready_to_switch_on()
      method on_switched_on (line 571) | void on_switched_on()
      method on_operation_enabled (line 587) | void on_operation_enabled()
      method start_sync_pos_mode (line 674) | void start_sync_pos_mode()
      method start_profile_pos_mode (line 679) | void start_profile_pos_mode()
      method start_interpolated_pos_mode (line 685) | void start_interpolated_pos_mode()
      method start_homing_mode (line 691) | void start_homing_mode()
      method start_profile_velocity_mode (line 696) | void start_profile_velocity_mode()
      method on_quickstop_active (line 702) | void on_quickstop_active()
      method is_shutdown (line 714) | bool is_shutdown()
      method is_disable_voltage (line 730) | bool is_disable_voltage()
      method is_switch_on (line 744) | bool is_switch_on()
      method is_enable_operation (line 760) | bool is_enable_operation()
      method is_quickstop (line 776) | bool is_quickstop()
      method is_faul_reset (line 790) | bool is_faul_reset()
      method OnWrite (line 803) | void OnWrite(uint16_t idx, uint8_t subidx) noexcept override
    class DelayedBootSlave (line 848) | class DelayedBootSlave : public ros2_canopen::CIA402MockSlave
      method DelayedReset (line 853) | void DelayedReset()
    class CIA402Slave (line 867) | class CIA402Slave : public BaseSlave
      method CIA402Slave (line 870) | explicit CIA402Slave(const std::string & node_name, bool intra_proce...
      method run (line 875) | void run() override

FILE: canopen_fake_slaves/include/canopen_fake_slaves/motion_generator.hpp
  class MotionGenerator (line 73) | class MotionGenerator

FILE: canopen_fake_slaves/launch/basic_slave.launch.py
  function generate_launch_description (line 34) | def generate_launch_description():

FILE: canopen_fake_slaves/launch/cia402_slave.launch.py
  function generate_launch_description (line 34) | def generate_launch_description():

FILE: canopen_fake_slaves/src/basic_slave.cpp
  function main (line 18) | int main(int argc, char * argv[])

FILE: canopen_fake_slaves/src/cia402_slave.cpp
  function main (line 18) | int main(int argc, char * argv[])

FILE: canopen_master_driver/include/canopen_master_driver/lely_master_bridge.hpp
  type ros2_canopen (line 31) | namespace ros2_canopen
    class LelyMasterBridge (line 41) | class LelyMasterBridge : public lely::canopen::AsyncMaster
      method LelyMasterBridge (line 64) | LelyMasterBridge(
      method submit_write_sdo (line 104) | void submit_write_sdo(uint8_t id, uint16_t idx, uint8_t subidx, T va...
      method submit_read_sdo (line 127) | void submit_read_sdo(uint8_t id, uint16_t idx, uint8_t subidx)

FILE: canopen_master_driver/include/canopen_master_driver/lifecycle_master_driver.hpp
  type ros2_canopen (line 25) | namespace ros2_canopen
    class LifecycleMasterDriver (line 35) | class LifecycleMasterDriver : public ros2_canopen::LifecycleCanopenMaster

FILE: canopen_master_driver/include/canopen_master_driver/master_driver.hpp
  type ros2_canopen (line 21) | namespace ros2_canopen
    class MasterDriver (line 31) | class MasterDriver : public ros2_canopen::CanopenMaster

FILE: canopen_master_driver/include/canopen_master_driver/node_interfaces/node_canopen_basic_master.hpp
  type ros2_canopen (line 24) | namespace ros2_canopen
    type node_interfaces (line 26) | namespace node_interfaces
      class NodeCanopenBasicMaster (line 29) | class NodeCanopenBasicMaster : public ros2_canopen::node_interfaces:...
        method NodeCanopenBasicMaster (line 42) | NodeCanopenBasicMaster(NODETYPE * node)

FILE: canopen_master_driver/src/lely_master_bridge.cpp
  type ros2_canopen (line 21) | namespace ros2_canopen /* constant-expression */

FILE: canopen_master_driver/src/lifecycle_master_driver.cpp
  type ros2_canopen (line 18) | namespace ros2_canopen

FILE: canopen_master_driver/src/master_driver.cpp
  type ros2_canopen (line 18) | namespace ros2_canopen

FILE: canopen_master_driver/src/node_interfaces/node_canopen_basic_master.cpp
  class ros2_canopen::node_interfaces::NodeCanopenBasicMaster<rclcpp::Node> (line 21) | class ros2_canopen::node_interfaces::NodeCanopenBasicMaster<rclcpp::Node>
  class ros2_canopen::node_interfaces::NodeCanopenBasicMaster<
  rclcpp_lifecycle::LifecycleNode> (line 22) | class ros2_canopen::node_interfaces::NodeCanopenBasicMaster<

FILE: canopen_master_driver/test/test_master_driver_component.cpp
  function TEST (line 24) | TEST(MasterDriverComponent, test_load_lifecycle_master_driver)
  function TEST (line 42) | TEST(MasterDriverComponent, test_load_master_driver)

FILE: canopen_master_driver/test/test_node_canopen_basic_master.cpp
  class RclCppFixture (line 18) | class RclCppFixture
    method RclCppFixture (line 21) | RclCppFixture()
  function TEST (line 39) | TEST(NodeCanopenBasicMaster, test_bad_sequence_configure)
  function TEST (line 46) | TEST(NodeCanopenBasicMaster, test_bad_sequence_activate)
  function TEST (line 53) | TEST(NodeCanopenBasicMaster, test_good_sequence)

FILE: canopen_master_driver/test/test_node_canopen_basic_master_ros.cpp
  function TEST (line 20) | TEST(NodeCanopenBasicMaster, test_good_sequence_advanced)
  function TEST (line 56) | TEST(NodeCanopenBasicLifecycleMaster, test_good_sequence_advanced)

FILE: canopen_proxy_driver/include/canopen_proxy_driver/lifecycle_proxy_driver.hpp
  type ros2_canopen (line 21) | namespace ros2_canopen
    class LifecycleProxyDriver (line 29) | class LifecycleProxyDriver : public ros2_canopen::LifecycleCanopenDriver
      method reset_node_nmt_command (line 36) | virtual bool reset_node_nmt_command()
      method start_node_nmt_command (line 41) | virtual bool start_node_nmt_command()
      method tpdo_transmit (line 46) | virtual bool tpdo_transmit(ros2_canopen::COData & data)
      method sdo_write (line 51) | virtual bool sdo_write(ros2_canopen::COData & data)
      method sdo_read (line 56) | virtual bool sdo_read(ros2_canopen::COData & data)
      method register_nmt_state_cb (line 61) | void register_nmt_state_cb(std::function<void(canopen::NmtState, uin...
      method register_rpdo_cb (line 66) | void register_rpdo_cb(std::function<void(COData, uint8_t)> rpdo_cb)

FILE: canopen_proxy_driver/include/canopen_proxy_driver/node_interfaces/node_canopen_proxy_driver.hpp
  type ros2_canopen (line 19) | namespace ros2_canopen
    type node_interfaces (line 21) | namespace node_interfaces
      class NodeCanopenProxyDriver (line 25) | class NodeCanopenProxyDriver : public NodeCanopenBaseDriver<NODETYPE>

FILE: canopen_proxy_driver/include/canopen_proxy_driver/proxy_driver.hpp
  type ros2_canopen (line 20) | namespace ros2_canopen
    class ProxyDriver (line 28) | class ProxyDriver : public ros2_canopen::CanopenDriver
      method reset_node_nmt_command (line 35) | virtual bool reset_node_nmt_command()
      method start_node_nmt_command (line 40) | virtual bool start_node_nmt_command()
      method tpdo_transmit (line 45) | virtual bool tpdo_transmit(ros2_canopen::COData & data)
      method sdo_write (line 50) | virtual bool sdo_write(ros2_canopen::COData & data)
      method sdo_read (line 55) | virtual bool sdo_read(ros2_canopen::COData & data)
      method register_nmt_state_cb (line 60) | void register_nmt_state_cb(std::function<void(canopen::NmtState, uin...
      method register_rpdo_cb (line 65) | void register_rpdo_cb(std::function<void(COData, uint8_t)> rpdo_cb)
      method register_emcy_cb (line 70) | void register_emcy_cb(std::function<void(COEmcy, uint8_t)> emcy_cb)

FILE: canopen_proxy_driver/src/node_interfaces/node_canopen_proxy_driver.cpp
  class ros2_canopen::node_interfaces::NodeCanopenProxyDriver<rclcpp::Node> (line 20) | class ros2_canopen::node_interfaces::NodeCanopenProxyDriver<rclcpp::Node>
  class ros2_canopen::node_interfaces::NodeCanopenProxyDriver<
  rclcpp_lifecycle::LifecycleNode> (line 21) | class ros2_canopen::node_interfaces::NodeCanopenProxyDriver<

FILE: canopen_proxy_driver/test/test_driver_component.cpp
  function TEST (line 24) | TEST(ComponentLoad, test_load_component_1)
  function TEST (line 42) | TEST(ComponentLoad, test_load_component_2)

FILE: canopen_proxy_driver/test/test_node_interface.cpp
  function TEST (line 20) | TEST(NodeCanopenProxyDriver, test_good_sequence_advanced)
  function TEST (line 55) | TEST(NodeCanopenBasicLifecycleMaster, test_good_sequence_advanced)

FILE: canopen_ros2_control/include/canopen_ros2_control/canopen_system.hpp
  type canopen_ros2_control (line 45) | namespace canopen_ros2_control
    function makeMemcpyCaster (line 48) | auto makeMemcpyCaster(const SourceType & source)
    type Ros2ControlCOData (line 62) | struct Ros2ControlCOData
      method set_co_data_type (line 75) | void set_co_data_type(const std::string & type)
    type RORos2ControlCOData (line 96) | struct RORos2ControlCOData : public Ros2ControlCOData
      method set_data (line 98) | void set_data(ros2_canopen::COData d) { original_data = d; }
      method prepare_data (line 100) | void prepare_data()
    type WORos2ControlCoData (line 160) | struct WORos2ControlCoData : public Ros2ControlCOData
      method WORos2ControlCoData (line 162) | WORos2ControlCoData() : one_shot(std::numeric_limits<double>::quiet_...
      method write_command (line 167) | bool write_command()
      method prepare_data (line 177) | void prepare_data()
    type Ros2ControlEmcyData (line 230) | struct Ros2ControlEmcyData
      method Ros2ControlEmcyData (line 232) | Ros2ControlEmcyData()
      method set_emcy (line 243) | void set_emcy(ros2_canopen::COEmcy e)
    type Ros2ControlNmtState (line 279) | struct Ros2ControlNmtState
      method Ros2ControlNmtState (line 281) | Ros2ControlNmtState()
      method set_state (line 289) | void set_state(canopen::NmtState s)
      method reset_command (line 295) | bool reset_command()
      method start_command (line 305) | bool start_command()
    type pair_hash (line 325) | struct pair_hash
    type CanopenNodeData (line 337) | struct CanopenNodeData
      method set_rpdo_data (line 354) | void set_rpdo_data(ros2_canopen::COData d)
      method get_rpdo_raw_data (line 386) | uint32_t get_rpdo_raw_data(uint16_t index, uint8_t subindex)
      method get_rpdo_data (line 402) | double get_rpdo_data(uint16_t index, uint8_t subindex)
    class CanopenSystem (line 418) | class CanopenSystem : public hardware_interface::SystemInterface

FILE: canopen_ros2_control/include/canopen_ros2_control/cia402_data.hpp
  type canopen_ros2_control (line 31) | namespace canopen_ros2_control
    type Cia402Data (line 33) | struct Cia402Data
      method init_data (line 56) | bool init_data(hardware_interface::ComponentInfo & joint, std::strin...
      method export_state_interface (line 115) | void export_state_interface(std::vector<hardware_interface::StateInt...
      method export_command_interface (line 130) | void export_command_interface(
      method read_state (line 161) | void read_state()
      method write_target (line 168) | void write_target()
      method perform_switch (line 193) | bool perform_switch()
      method check_id (line 218) | bool check_id(uint8_t id)

FILE: canopen_ros2_control/include/canopen_ros2_control/cia402_system.hpp
  type canopen_ros2_control (line 34) | namespace canopen_ros2_control
    type MotorTriggerCommand (line 37) | struct MotorTriggerCommand
      method is_commanded (line 42) | bool is_commanded()
      method set_response (line 49) | void set_response(bool response) { resp = response ? kResponseOk : k...
    type MotorTarget (line 52) | struct MotorTarget : public MotorTriggerCommand
    type MotorNodeData (line 59) | struct MotorNodeData
    class Cia402System (line 84) | class Cia402System : public CanopenSystem
      method CANOPEN_ROS2_CONTROL__VISIBILITY_PUBLIC (line 89) | CANOPEN_ROS2_CONTROL__VISIBILITY_PUBLIC
      method getMotorKey (line 123) | std::pair<uint, uint> getMotorKey(uint node_id, uint channel = 0) const

FILE: canopen_ros2_control/include/canopen_ros2_control/helpers.hpp
  type canopen_ros2_control (line 25) | namespace canopen_ros2_control
    type TriggerCommand (line 42) | struct TriggerCommand
      method try_trigger (line 48) | bool try_trigger()

FILE: canopen_ros2_control/include/canopen_ros2_control/robot_system.hpp
  type canopen_ros2_control (line 31) | namespace canopen_ros2_control
    class RobotSystem (line 33) | class RobotSystem : public hardware_interface::SystemInterface
      method CANOPEN_ROS2_CONTROL__VISIBILITY_PUBLIC (line 36) | CANOPEN_ROS2_CONTROL__VISIBILITY_PUBLIC
      method CANOPEN_ROS2_CONTROL__VISIBILITY_PUBLIC (line 38) | CANOPEN_ROS2_CONTROL__VISIBILITY_PUBLIC

FILE: canopen_ros2_control/src/canopen_system.cpp
  type canopen_ros2_control (line 36) | namespace canopen_ros2_control

FILE: canopen_ros2_control/src/cia402_system.cpp
  type canopen_ros2_control (line 33) | namespace canopen_ros2_control

FILE: canopen_ros2_control/test/test_canopen_system.cpp
  class TestCanopenSystem (line 33) | class TestCanopenSystem : public ::testing::Test
    method SetUp (line 36) | void SetUp() override
  function TEST_F (line 62) | TEST_F(TestCanopenSystem, load_canopen_system_2dof)

FILE: canopen_ros2_controllers/include/canopen_ros2_controllers/canopen_proxy_controller.hpp
  type CommandInterfaces (line 37) | enum CommandInterfaces
  type StateInterfaces (line 50) | enum StateInterfaces
  type canopen_ros2_controllers (line 61) | namespace canopen_ros2_controllers
    class CanopenProxyController (line 64) | class CanopenProxyController : public controller_interface::Controller...

FILE: canopen_ros2_controllers/include/canopen_ros2_controllers/cia402_device_controller.hpp
  type Cia402CommandInterfaces (line 26) | enum Cia402CommandInterfaces
  type Cia402StateInterfaces (line 46) | enum Cia402StateInterfaces
  type canopen_ros2_controllers (line 53) | namespace canopen_ros2_controllers
    class Cia402DeviceController (line 56) | class Cia402DeviceController : public canopen_ros2_controllers::Canope...
      method createTriggerSrv (line 86) | inline rclcpp::Service<std_srvs::srv::Trigger>::SharedPtr createTrig...

FILE: canopen_ros2_controllers/src/canopen_proxy_controller.cpp
  function propagate_controller_command_msg (line 38) | bool propagate_controller_command_msg(std::shared_ptr<ControllerCommandM...
  type canopen_ros2_controllers (line 47) | namespace canopen_ros2_controllers

FILE: canopen_ros2_controllers/src/cia402_device_controller.cpp
  function reset_controller_command_msg (line 31) | void reset_controller_command_msg(
  type canopen_ros2_controllers (line 38) | namespace canopen_ros2_controllers

FILE: canopen_ros2_controllers/test/test_canopen_proxy_controller.cpp
  class CanopenProxyControllerTest (line 24) | class CanopenProxyControllerTest
  function TEST_P (line 31) | TEST_P(CanopenProxyControllerTestParameterizedParameters, one_parameter_...
  function TEST_F (line 44) | TEST_F(CanopenProxyControllerTest, joint_names_parameter_not_set)
  function TEST_F (line 55) | TEST_F(CanopenProxyControllerTest, all_parameters_set_configure_success)
  function TEST_F (line 68) | TEST_F(CanopenProxyControllerTest, check_exported_intefaces)
  function TEST_F (line 89) | TEST_F(CanopenProxyControllerTest, activate_success)
  function TEST_F (line 101) | TEST_F(CanopenProxyControllerTest, update_success)
  function TEST_F (line 113) | TEST_F(CanopenProxyControllerTest, deactivate_success)
  function TEST_F (line 122) | TEST_F(CanopenProxyControllerTest, reactivate_success)
  function TEST_F (line 148) | TEST_F(CanopenProxyControllerTest, test_sequence_configure_activate)
  function TEST_F (line 160) | TEST_F(CanopenProxyControllerTest, test_update_logic_fast)

FILE: canopen_ros2_controllers/test/test_canopen_proxy_controller.hpp
  class TestableCanopenProxyController (line 49) | class TestableCanopenProxyController : public canopen_ros2_controllers::...
    method on_configure (line 60) | controller_interface::CallbackReturn on_configure(
    method wait_for_command (line 79) | bool wait_for_command(
    method wait_for_commands (line 91) | bool wait_for_commands(
  class CanopenProxyControllerFixture (line 106) | class CanopenProxyControllerFixture : public ::testing::Test
    method SetUpTestCase (line 109) | static void SetUpTestCase() { rclcpp::init(0, nullptr); }
    method SetUp (line 111) | void SetUp()
    method TearDownTestCase (line 125) | static void TearDownTestCase() { rclcpp::shutdown(); }
    method TearDown (line 127) | void TearDown() { controller_.reset(nullptr); }
    method SetUpController (line 130) | void SetUpController(
    method subscribe_and_get_messages (line 165) | void subscribe_and_get_messages(ControllerStateMsg & msg)
    method publish_commands (line 201) | void publish_commands(
  class CanopenProxyControllerTestParameterizedParameters (line 259) | class CanopenProxyControllerTestParameterizedParameters
    method SetUp (line 264) | virtual void SetUp() { CanopenProxyControllerFixture::SetUp(); }
    method TearDownTestCase (line 266) | static void TearDownTestCase() { CanopenProxyControllerFixture::TearDo...
    method SetUpController (line 269) | void SetUpController(bool set_parameters = true)

FILE: canopen_ros2_controllers/test/test_load_canopen_proxy_controller.cpp
  function TEST (line 24) | TEST(TestLoadCanopenProxyController, load_controller)

FILE: canopen_ros2_controllers/test/test_load_cia402_device_controller.cpp
  function TEST (line 24) | TEST(TestLoadCanopenProxyController, load_controller)

FILE: canopen_ros2_controllers/test/test_load_cia402_robot_controller.cpp
  function TEST (line 24) | TEST(TestLoadCanopenProxyController, load_controller)

FILE: canopen_tests/launch/canopen_system.launch.py
  function launch_setup (line 45) | def launch_setup(context, *args, **kwargs):
  function generate_launch_description (line 180) | def generate_launch_description():

FILE: canopen_tests/launch/cia402_diagnostics_setup.launch.py
  function generate_launch_description (line 24) | def generate_launch_description():

FILE: canopen_tests/launch/cia402_lifecycle_setup.launch.py
  function generate_launch_description (line 23) | def generate_launch_description():

FILE: canopen_tests/launch/cia402_namespaced_system.launch.py
  function launch_setup (line 47) | def launch_setup(context, *args, **kwargs):
  function generate_launch_description (line 195) | def generate_launch_description():

FILE: canopen_tests/launch/cia402_setup.launch.py
  function generate_launch_description (line 23) | def generate_launch_description():

FILE: canopen_tests/launch/cia402_system.launch.py
  function launch_setup (line 45) | def launch_setup(context, *args, **kwargs):
  function generate_launch_description (line 177) | def generate_launch_description():

FILE: canopen_tests/launch/proxy_diagnostics_setup.launch.py
  function generate_launch_description (line 24) | def generate_launch_description():

FILE: canopen_tests/launch/proxy_lifecycle_setup.launch.py
  function generate_launch_description (line 23) | def generate_launch_description():

FILE: canopen_tests/launch/proxy_setup.launch.py
  function generate_launch_description (line 24) | def generate_launch_description():

FILE: canopen_tests/launch/proxy_setup_namespaced.launch.py
  function generate_launch_description (line 24) | def generate_launch_description():

FILE: canopen_tests/launch/robot_control_setup.launch.py
  function generate_launch_description (line 24) | def generate_launch_description():

FILE: canopen_tests/launch/view_urdf.launch.py
  function generate_launch_description (line 22) | def generate_launch_description():

FILE: canopen_tests/launch_tests/test_cia402_driver.py
  function generate_test_description (line 36) | def generate_test_description():
  class TestSDO (line 55) | class TestSDO(unittest.TestCase):
    method run_node (line 56) | def run_node(self):
    method setUp (line 61) | def setUp(cls):
    method tearDown (line 69) | def tearDown(cls):
    method test_sdo_read (line 75) | def test_sdo_read(self):
    method test_init (line 86) | def test_init(self):
    method test_position_mode (line 94) | def test_position_mode(self):

FILE: canopen_tests/launch_tests/test_proxy_driver.py
  function generate_test_description (line 36) | def generate_test_description():
  class TestNMT (line 55) | class TestNMT(unittest.TestCase):
    method run_node (line 56) | def run_node(self):
    method setUpClass (line 61) | def setUpClass(cls):
    method tearDownClass (line 69) | def tearDownClass(cls):
    method test_reset_nmt (line 75) | def test_reset_nmt(self):
  class TestSDO (line 83) | class TestSDO(unittest.TestCase):
    method run_node (line 84) | def run_node(self):
    method setUp (line 89) | def setUp(cls):
    method tearDown (line 97) | def tearDown(cls):
    method test_sdo_read (line 103) | def test_sdo_read(self):
    method test_sdo_write (line 115) | def test_sdo_write(self):
    method test_sdo_write_signed8 (line 147) | def test_sdo_write_signed8(self):
    method test_sdo_write_signed16 (line 180) | def test_sdo_write_signed16(self):
    method test_sdo_write_signed32 (line 213) | def test_sdo_write_signed32(self):
    method test_sdo_write_unsigned8 (line 246) | def test_sdo_write_unsigned8(self):
    method test_sdo_write_unsigned16 (line 279) | def test_sdo_write_unsigned16(self):
    method test_sdo_write_unsigned32 (line 312) | def test_sdo_write_unsigned32(self):
  class TestSDOMaster (line 346) | class TestSDOMaster(unittest.TestCase):
    method run_node (line 347) | def run_node(self):
    method setUp (line 352) | def setUp(cls):
    method tearDown (line 360) | def tearDown(cls):
    method test_sdo_read (line 366) | def test_sdo_read(self):
    method test_sdo_write (line 381) | def test_sdo_write(self):
  class TestPDO (line 410) | class TestPDO(unittest.TestCase):
    method run_node (line 411) | def run_node(self):
    method setUp (line 416) | def setUp(cls):
    method tearDown (line 424) | def tearDown(cls):
    method test_pdo (line 430) | def test_pdo(self):

FILE: canopen_tests/launch_tests/test_proxy_driver_namespaced.py
  function generate_test_description (line 36) | def generate_test_description():
  class TestNMT (line 55) | class TestNMT(unittest.TestCase):
    method run_node (line 56) | def run_node(self):
    method setUpClass (line 61) | def setUpClass(cls):
    method tearDownClass (line 69) | def tearDownClass(cls):
    method test_reset_nmt (line 75) | def test_reset_nmt(self):
  class TestSDO (line 85) | class TestSDO(unittest.TestCase):
    method run_node (line 86) | def run_node(self):
    method setUp (line 91) | def setUp(cls):
    method tearDown (line 99) | def tearDown(cls):
    method test_sdo_read (line 105) | def test_sdo_read(self):
    method test_sdo_write (line 117) | def test_sdo_write(self):
  class TestSDOMaster (line 150) | class TestSDOMaster(unittest.TestCase):
    method run_node (line 151) | def run_node(self):
    method setUp (line 156) | def setUp(cls):
    method tearDown (line 164) | def tearDown(cls):
    method test_sdo_read (line 170) | def test_sdo_read(self):
    method test_sdo_write (line 185) | def test_sdo_write(self):
  class TestPDO (line 214) | class TestPDO(unittest.TestCase):
    method run_node (line 215) | def run_node(self):
    method setUp (line 220) | def setUp(cls):
    method tearDown (line 228) | def tearDown(cls):
    method test_pdo (line 234) | def test_pdo(self):

FILE: canopen_tests/launch_tests/test_proxy_lifecycle_driver.py
  function generate_test_description (line 36) | def generate_test_description():
  class TestLifecycle (line 55) | class TestLifecycle(unittest.TestCase):
    method run_node (line 56) | def run_node(self):
    method setUp (line 61) | def setUp(cls):
    method tearDown (line 69) | def tearDown(cls):
    method test_configure_unconfigure (line 75) | def test_configure_unconfigure(self):
    method test_full_cycle (line 87) | def test_full_cycle(self):
  class TestSDO (line 122) | class TestSDO(unittest.TestCase):
    method run_node (line 123) | def run_node(self):
    method setUp (line 128) | def setUp(cls):
    method tearDown (line 136) | def tearDown(cls):
    method test_full_cycle_sdo (line 142) | def test_full_cycle_sdo(self):
  class TestPDO (line 206) | class TestPDO(unittest.TestCase):
    method run_node (line 207) | def run_node(self):
    method setUp (line 212) | def setUp(cls):
    method tearDown (line 220) | def tearDown(cls):
    method test_full_cycle_sdo (line 226) | def test_full_cycle_sdo(self):

FILE: canopen_tests/launch_tests/test_robot_control.py
  function generate_test_description (line 37) | def generate_test_description():
  class TestSDO (line 56) | class TestSDO(unittest.TestCase):
    method run_node (line 57) | def run_node(self):
    method setUp (line 62) | def setUp(cls):
    method tearDown (line 70) | def tearDown(cls):
    method test_sdo_read (line 76) | def test_sdo_read(self):
    method test_forward_control (line 87) | def test_forward_control(self):

FILE: canopen_utils/canopen_utils/cyclic_tester.py
  class DoubleTalker (line 22) | class DoubleTalker(Node):
    method __init__ (line 25) | def __init__(self):
    method timer_callback (line 39) | def timer_callback(self):
  function main (line 49) | def main(args=None):

FILE: canopen_utils/canopen_utils/launch_test_node.py
  class Ros2ActiveIoHandler (line 33) | class Ros2ActiveIoHandler:
    method __init__ (line 34) | def __init__(self, proc_output: launch_testing.ActiveIoHandler):
    method checkInRos2Stream (line 37) | def checkInRos2Stream(self, process, expected_output: str):
    method waitFor (line 53) | def waitFor(self, process, expected_output: str, timeout: float = 1.0):
    method assertWaitFor (line 67) | def assertWaitFor(self, process, expected_output: str, timeout: float ...
  class LaunchTestNode (line 72) | class LaunchTestNode(Node):
    method __init__ (line 73) | def __init__(self):
    method publish_delayed (line 77) | def publish_delayed(self, publisher: Publisher, msg, delay: float):
    method publish_and_check_output (line 81) | def publish_and_check_output(
    method subscribe_and_wait_for_message (line 95) | def subscribe_and_wait_for_message(self, topic: str, msg_type, msg, ti...
    method call_service (line 112) | def call_service(
    method publish_message (line 136) | def publish_message(self, topic_name: str, topic_type, msg):

FILE: canopen_utils/canopen_utils/simple_rpdo_tpdo_tester.py
  class SimpleTestNode (line 25) | class SimpleTestNode(Node):
    method __init__ (line 26) | def __init__(self, name="test_node"):
    method checkRpdoTpdo (line 29) | def checkRpdoTpdo(self, node_name, index: int, subindex: int, type: in...
    method rpdo_callback (line 57) | def rpdo_callback(self, msg):
  function main (line 63) | def main(args=None):

FILE: canopen_utils/canopen_utils/test_node.py
  class TestNode (line 24) | class TestNode(Node):
    method __init__ (line 25) | def __init__(self, name="test_node"):
    method checkTransition (line 28) | def checkTransition(self, node_name: str, state: int, tranisition: int...
    method checkTrigger (line 55) | def checkTrigger(self, node_name, service_name) -> bool:
    method checkSDORead (line 66) | def checkSDORead(self, node_name, index: int, subindex: int, data: int...
    method checkSDOWrite (line 79) | def checkSDOWrite(self, node_name, index: int, subindex: int, data: in...
    method checkSDOReadID (line 93) | def checkSDOReadID(
    method checkSDOWriteID (line 110) | def checkSDOWriteID(
    method checkRpdoTpdo (line 128) | def checkRpdoTpdo(self, node_name, index: int, subindex: int, data: in...
    method rpdo_callback (line 151) | def rpdo_callback(self, msg):

FILE: canopen_utils/no_tests/_test_copyright.py
  function test_copyright (line 21) | def test_copyright():

FILE: canopen_utils/no_tests/_test_flake8.py
  function test_flake8 (line 21) | def test_flake8():

FILE: canopen_utils/no_tests/_test_pep257.py
  function test_pep257 (line 21) | def test_pep257():

FILE: lely_core_libraries/cogen/cogen.py
  function main (line 21) | def main():
Condensed preview — 340 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,675K chars).
[
  {
    "path": ".clang-format",
    "chars": 338,
    "preview": "---\nLanguage: Cpp\nBasedOnStyle: Google\n\nAccessModifierOffset: -2\nAlignAfterOpenBracket: AlwaysBreak\nBreakBeforeBraces: A"
  },
  {
    "path": ".codespellignore",
    "chars": 4,
    "preview": "ons\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 458,
    "preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: bug\nassignees: ''\n\n---\n\n**Describe the "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 604,
    "preview": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: enhancement\nassignees: ''\n\n---\n\n**Is"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/question.md",
    "chars": 364,
    "preview": "---\nname: Question\nabout: Create a report to help us improve\ntitle: ''\nlabels: question\nassignees: ''\n\n---\n\n**Describe t"
  },
  {
    "path": ".github/dependabot.yaml",
    "chars": 216,
    "preview": "# Set update schedule for GitHub Actions\n\nversion: 2\nupdates:\n\n  - package-ecosystem: \"github-actions\"\n    directory: \"/"
  },
  {
    "path": ".github/workflows/ci-format.yml",
    "chars": 586,
    "preview": "# This is a format job. Pre-commit has a first-party GitHub action, so we use\n# that: https://github.com/pre-commit/acti"
  },
  {
    "path": ".github/workflows/ci-ros-lint.yml.backup",
    "chars": 937,
    "preview": "name: ROS Lint\non:\n  pull_request:\n\njobs:\n  ament_lint:\n    name: ament_${{ matrix.linter }}\n    runs-on: ubuntu-20.04\n "
  },
  {
    "path": ".github/workflows/docker.yml",
    "chars": 1015,
    "preview": "name: Create and publish a Docker image\non:\n  push:\n    branches: ['master']\n  workflow_dispatch:\n\nenv:\n  REGISTRY: ghcr"
  },
  {
    "path": ".github/workflows/humble.yml",
    "chars": 977,
    "preview": "name: Industrial CI Humble\r\n\r\non:\r\n  push:\r\n    branches: [ humble ]\r\n  pull_request:\r\n    branches: [ humble ]\r\n  workf"
  },
  {
    "path": ".github/workflows/humble_documentation.yml",
    "chars": 2231,
    "preview": "name: Documentation Humble\n\n# Controls when the workflow will run\non:\n  # Triggers the workflow on push or pull request "
  },
  {
    "path": ".github/workflows/prerelease-rolling.yml",
    "chars": 749,
    "preview": "name: Prerelease-Test Rolling\n\non:\n  workflow_dispatch:\n  push:\n    tags:\n      - \"*\"\n\njobs:\n  industrial_ci:\n    name: "
  },
  {
    "path": ".github/workflows/rolling.yml",
    "chars": 1383,
    "preview": "name: Industrial CI\r\n\r\non:\r\n  push:\r\n    branches: [ master ]\r\n  pull_request:\r\n    branches: [ master ]\r\n  workflow_dis"
  },
  {
    "path": ".github/workflows/rolling_documentation.yml",
    "chars": 2393,
    "preview": "name: Documentation\n\n# Controls when the workflow will run\non:\n  # Triggers the workflow on push or pull request events "
  },
  {
    "path": ".gitignore",
    "chars": 57,
    "preview": ".vscode/\n**/doc_output/\n**/__pycache__/\n**/_build\n**/api\n"
  },
  {
    "path": ".pre-commit-config.yaml",
    "chars": 2799,
    "preview": "# To use:\n#\n#     pre-commit run -a\n#\n# Or:\n#\n#     pre-commit install  # (runs every time you commit in git)\n#\n# To upd"
  },
  {
    "path": "Dockerfile",
    "chars": 493,
    "preview": "FROM ros:rolling-ros-core\n\n\nRUN apt-get update \\\n    && apt-get install -y \\\n        python3-rosdep \\\n        python3-ar"
  },
  {
    "path": "README.md",
    "chars": 21149,
    "preview": "# ROS2 CANopen\n\n## Status\n\n| Build Process | Status |\n|---------------|--------|\n| Industrial CI Build | [![Industrial C"
  },
  {
    "path": "canopen/CHANGELOG.rst",
    "chars": 4721,
    "preview": "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nChangelog for package canopen\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n0.3.2 (2025-12-05)\n----------"
  },
  {
    "path": "canopen/CMakeLists.txt",
    "chars": 109,
    "preview": "cmake_minimum_required(VERSION 3.8)\nproject(canopen NONE)\nfind_package(ament_cmake REQUIRED)\nament_package()\n"
  },
  {
    "path": "canopen/LICENSE",
    "chars": 11355,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "canopen/doxygen/Doxyfile",
    "chars": 710,
    "preview": "# All settings not listed here will use the Doxygen default values.\n\nPROJECT_NAME           = \"ros2_canopen\"\nPROJECT_NUM"
  },
  {
    "path": "canopen/package.xml",
    "chars": 1020,
    "preview": "<?xml version=\"1.0\"?>\n<?xml-model href=\"http://download.ros.org/schema/package_format3.xsd\" schematypens=\"http://www.w3."
  },
  {
    "path": "canopen/sphinx/Makefile",
    "chars": 749,
    "preview": "# Minimal makefile for Sphinx documentation\n#\n\n# You can set these variables from the command line, and also\n# from the "
  },
  {
    "path": "canopen/sphinx/_static/css/custom.css",
    "chars": 192,
    "preview": "\n.wy-table-responsive table td,\n.wy-table-responsive table th {\n white-space:normal;\n}\n\ntr {\n    white-space: normal;\n}\n"
  },
  {
    "path": "canopen/sphinx/application/prbt_robot.rst",
    "chars": 17785,
    "preview": "Pilz manipulator PRBT 6\n=======================\n\nThis guide provides instructions on how to set up Pilz manipulators PRB"
  },
  {
    "path": "canopen/sphinx/application/trinamic.rst",
    "chars": 7292,
    "preview": "Trinamic Stepper Motor control\n==============================\n\nIntroduction\n------------\n\nThis tutorial is a simple exam"
  },
  {
    "path": "canopen/sphinx/conf.py",
    "chars": 3369,
    "preview": "# Copyright 2023 ROS-Industrial\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use th"
  },
  {
    "path": "canopen/sphinx/developers-guide/architecture.rst",
    "chars": 9516,
    "preview": "Architecture\n=============\n\nThe architecture of the ROS2 CANopen stack is based on the composition\nconcept of ROS2. In R"
  },
  {
    "path": "canopen/sphinx/developers-guide/design-objectives.rst",
    "chars": 1611,
    "preview": "Design Objectives\n======================\n\nThe ros_canopen stack had a number of drawbacks especially when it came\nto mai"
  },
  {
    "path": "canopen/sphinx/developers-guide/new-device-manager.rst",
    "chars": 58,
    "preview": "Creating your device manager\n============================\n"
  },
  {
    "path": "canopen/sphinx/developers-guide/new-driver.rst",
    "chars": 10909,
    "preview": "Creating a new device driver\n============================\n\nCreating your own device driver is fairly easy in ros2_canope"
  },
  {
    "path": "canopen/sphinx/developers-guide/new-master.rst",
    "chars": 44,
    "preview": "Creating a new master\n=====================\n"
  },
  {
    "path": "canopen/sphinx/developers-guide/overview.rst",
    "chars": 1491,
    "preview": "Overview\n========\nros2_canopen provides nodes for interfacing with CANopen devices. The library builds upon the professi"
  },
  {
    "path": "canopen/sphinx/index.rst",
    "chars": 1004,
    "preview": "ROS2 CANopen Stack\n==================\n\nThis is the documentation of the ROS2 CANopen stack.\n\n.. toctree::\n  :maxdepth: 1"
  },
  {
    "path": "canopen/sphinx/make.bat",
    "chars": 800,
    "preview": "@ECHO OFF\r\n\r\npushd %~dp0\r\n\r\nREM Command file for Sphinx documentation\r\n\r\nif \"%SPHINXBUILD%\" == \"\" (\r\n\tset SPHINXBUILD=sp"
  },
  {
    "path": "canopen/sphinx/quickstart/examples.rst",
    "chars": 830,
    "preview": "Running Examples\n================\n\nIn order to tryout the library a few examples are provided in the ``canopen_tests`` d"
  },
  {
    "path": "canopen/sphinx/quickstart/installation.rst",
    "chars": 354,
    "preview": "Installation\n===============================\nClone ros2_canopen into your ROS2 workspace's source folder, install depend"
  },
  {
    "path": "canopen/sphinx/quickstart/operation.rst",
    "chars": 880,
    "preview": "Setup CAN Controller\n====================\n.. _quick-start-setup-can-controller:\n\n**Option 1**: Virtual CANController\n\n.."
  },
  {
    "path": "canopen/sphinx/software-tests/proxy-driver-test.rst",
    "chars": 645,
    "preview": "Lifecycle Proxy Driver Test\n===========================\n\n.. csv-table:: Testdetails\n    :header: \"Detail\", \"Information\""
  },
  {
    "path": "canopen/sphinx/software-tests/ros2_control_system-test.rst",
    "chars": 2242,
    "preview": "ros2_control SystemInterface test\n=================================\n\nTest details\n------------\n\n.. csv-table:: Tests\n   "
  },
  {
    "path": "canopen/sphinx/user-guide/cia402-driver.rst",
    "chars": 4348,
    "preview": "Cia402 Driver\n========================\n\nThe Cia402 Driver implements the CIA402 profile for motion controllers and enabl"
  },
  {
    "path": "canopen/sphinx/user-guide/configuration.rst",
    "chars": 8408,
    "preview": "Configuration Package\n=====================\n\nA configuration package contains one or more configurations for the CANopen"
  },
  {
    "path": "canopen/sphinx/user-guide/how-to-create-a-cia301-system.rst",
    "chars": 5240,
    "preview": "How to create a cia301 system with ros2_control\n=================================================\n\nThe CiA 301 profile, "
  },
  {
    "path": "canopen/sphinx/user-guide/how-to-create-a-configuration.rst",
    "chars": 7444,
    "preview": "How to create a configuration package\n========================================\nIn order to use the ros2_canopen stack fo"
  },
  {
    "path": "canopen/sphinx/user-guide/how-to-create-a-robot-system.rst",
    "chars": 7297,
    "preview": "How to create a robot system with ros2_control\n==============================================\nThis guide describes how t"
  },
  {
    "path": "canopen/sphinx/user-guide/master.rst",
    "chars": 977,
    "preview": "Master Driver\n=============\n\nThe master driver handles the creation of the necessary can interface and sets up a canopen"
  },
  {
    "path": "canopen/sphinx/user-guide/operation/managed-service-interface.rst",
    "chars": 2489,
    "preview": "Managed Service Interface\n============================\n\n\nDevice Container with managed nodes\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\""
  },
  {
    "path": "canopen/sphinx/user-guide/operation/ros2-control-interface.rst",
    "chars": 2897,
    "preview": "Hardware Interface\n------------------\nThis package provides multiple hardware interfaces for testing. Mainly the followi"
  },
  {
    "path": "canopen/sphinx/user-guide/operation/service-interface.rst",
    "chars": 2243,
    "preview": "Service Interface\n==================\n\n\nDevice Container\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\nThe device container implements ROS2 component"
  },
  {
    "path": "canopen/sphinx/user-guide/operation.rst",
    "chars": 1867,
    "preview": "Operation\n=========\n\nThe ros2_canopen stack can be used in three different ways:\n\n* standard nodes container\n* managed n"
  },
  {
    "path": "canopen/sphinx/user-guide/proxy-driver.rst",
    "chars": 1381,
    "preview": "Proxy Driver\n===================\nA proxy driver which simply forwards CANopen functionality for a specific device via RO"
  },
  {
    "path": "canopen_402_driver/CHANGELOG.rst",
    "chars": 2320,
    "preview": "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nChangelog for package canopen_402_driver\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"
  },
  {
    "path": "canopen_402_driver/CMakeLists.txt",
    "chars": 4542,
    "preview": "cmake_minimum_required(VERSION 3.8)\nproject(canopen_402_driver)\n\nif(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MA"
  },
  {
    "path": "canopen_402_driver/LICENSE",
    "chars": 7632,
    "preview": "GNU LESSER GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foun"
  },
  {
    "path": "canopen_402_driver/include/canopen_402_driver/base.hpp",
    "chars": 2238,
    "preview": "//    Copyright 2023 Christoph Hellmann Santos\n//    Copyright 2014-2022 Authors of ros_canopen\n//\n// This program is fr"
  },
  {
    "path": "canopen_402_driver/include/canopen_402_driver/cia402_driver.hpp",
    "chars": 3333,
    "preview": "//    Copyright 2023 Christoph Hellmann Santos\n//\n// This program is free software: you can redistribute it and/or modif"
  },
  {
    "path": "canopen_402_driver/include/canopen_402_driver/command.hpp",
    "chars": 2648,
    "preview": "//    Copyright 2023 Christoph Hellmann Santos\n//    Copyright 2014-2022 Authors of ros_canopen\n//\n// This program is fr"
  },
  {
    "path": "canopen_402_driver/include/canopen_402_driver/default_homing_mode.hpp",
    "chars": 2035,
    "preview": "//    Copyright 2023 Christoph Hellmann Santos\n//    Copyright 2014-2022 Authors of ros_canopen\n//\n// This program is fr"
  },
  {
    "path": "canopen_402_driver/include/canopen_402_driver/homing_mode.hpp",
    "chars": 1278,
    "preview": "//    Copyright 2023 Christoph Hellmann Santos\n//    Copyright 2014-2022 Authors of ros_canopen\n//\n// This program is fr"
  },
  {
    "path": "canopen_402_driver/include/canopen_402_driver/lifecycle_cia402_driver.hpp",
    "chars": 2969,
    "preview": "//    Copyright 2023 Christoph Hellmann Santos\n//\n// This program is free software: you can redistribute it and/or modif"
  },
  {
    "path": "canopen_402_driver/include/canopen_402_driver/mode.hpp",
    "chars": 1618,
    "preview": "//    Copyright 2023 Christoph Hellmann Santos\n//    Copyright 2014-2022 Authors of ros_canopen\n//\n// This program is fr"
  },
  {
    "path": "canopen_402_driver/include/canopen_402_driver/mode_forward_helper.hpp",
    "chars": 1923,
    "preview": "//    Copyright 2023 Christoph Hellmann Santos\n//    Copyright 2014-2022 Authors of ros_canopen\n//\n// This program is fr"
  },
  {
    "path": "canopen_402_driver/include/canopen_402_driver/mode_target_helper.hpp",
    "chars": 2527,
    "preview": "//    Copyright 2023 Christoph Hellmann Santos\n//    Copyright 2014-2022 Authors of ros_canopen\n//\n// This program is fr"
  },
  {
    "path": "canopen_402_driver/include/canopen_402_driver/motor.hpp",
    "chars": 9951,
    "preview": "//    Copyright 2023 Christoph Hellmann Santos\n//    Copyright 2014-2022 Authors of ros_canopen\n//\n// This program is fr"
  },
  {
    "path": "canopen_402_driver/include/canopen_402_driver/node_interfaces/node_canopen_402_driver.hpp",
    "chars": 12960,
    "preview": "//    Copyright 2023 Christoph Hellmann Santos\n//                          Vishnuprasad Prachandabhanu\n//               "
  },
  {
    "path": "canopen_402_driver/include/canopen_402_driver/node_interfaces/node_canopen_402_driver_impl.hpp",
    "chars": 26215,
    "preview": "//    Copyright 2023 Christoph Hellmann Santos\n//                          Vishnuprasad Prachandabhanu\n//               "
  },
  {
    "path": "canopen_402_driver/include/canopen_402_driver/profiled_position_mode.hpp",
    "chars": 2889,
    "preview": "//    Copyright 2023 Christoph Hellmann Santos\n//    Copyright 2014-2022 Authors of ros_canopen\n//\n// This program is fr"
  },
  {
    "path": "canopen_402_driver/include/canopen_402_driver/state.hpp",
    "chars": 2065,
    "preview": "//    Copyright 2023 Christoph Hellmann Santos\n//    Copyright 2014-2022 Authors of ros_canopen\n//\n// This program is fr"
  },
  {
    "path": "canopen_402_driver/include/canopen_402_driver/visibility_control.h",
    "chars": 1958,
    "preview": "//    Copyright 2023 Christoph Hellmann Santos\n//\n// This program is free software: you can redistribute it and/or modif"
  },
  {
    "path": "canopen_402_driver/include/canopen_402_driver/word_accessor.hpp",
    "chars": 1473,
    "preview": "//    Copyright 2023 Christoph Hellmann Santos\n//    Copyright 2014-2022 Authors of ros_canopen\n//\n// This program is fr"
  },
  {
    "path": "canopen_402_driver/package.xml",
    "chars": 917,
    "preview": "<?xml version=\"1.0\"?>\n<?xml-model href=\"http://download.ros.org/schema/package_format3.xsd\" schematypens=\"http://www.w3."
  },
  {
    "path": "canopen_402_driver/src/cia402_driver.cpp",
    "chars": 1226,
    "preview": "//    Copyright 2023 Christoph Hellmann Santos\n//\n// This program is free software: you can redistribute it and/or modif"
  },
  {
    "path": "canopen_402_driver/src/command.cpp",
    "chars": 4197,
    "preview": "//    Copyright 2023 Christoph Hellmann Santos\n//    Copyright 2022 Authors of ros_canopen\n//\n// This program is free so"
  },
  {
    "path": "canopen_402_driver/src/default_homing_mode.cpp",
    "chars": 3570,
    "preview": "//    Copyright 2023 Christoph Hellmann Santos\n//    Copyright 2014-2022 Authors of ros_canopen\n//\n// This program is fr"
  },
  {
    "path": "canopen_402_driver/src/lifecycle_cia402_driver.cpp",
    "chars": 1291,
    "preview": "//    Copyright 2023 Christoph Hellmann Santos\n//\n// This program is free software: you can redistribute it and/or modif"
  },
  {
    "path": "canopen_402_driver/src/motor.cpp",
    "chars": 14482,
    "preview": "//    Copyright 2023 Christoph Hellmann Santos\n//    Copyright 2023 Vishnuprasad Prachandabhanu\n//    Copyright 2014-202"
  },
  {
    "path": "canopen_402_driver/src/node_interfaces/node_canopen_402_driver.cpp",
    "chars": 1127,
    "preview": "//    Copyright 2023 Christoph Hellmann Santos\n//\n// This program is free software: you can redistribute it and/or modif"
  },
  {
    "path": "canopen_402_driver/src/state.cpp",
    "chars": 2957,
    "preview": "//    Copyright 2023 Christoph Hellmann Santos\n//    Copyright 2014-2022 Authors of ros_canopen\n//\n// This program is fr"
  },
  {
    "path": "canopen_402_driver/test/CMakeLists.txt",
    "chars": 839,
    "preview": "ament_add_gtest(test_driver_component\ntest_driver_component.cpp\n)\ntarget_include_directories(test_driver_component PUBLI"
  },
  {
    "path": "canopen_402_driver/test/master.dcf",
    "chars": 10148,
    "preview": "[DeviceComissioning]\nNodeID=1\nNodeName=\nNodeRefd=\nBaudrate=1000\nNetNumber=1\nNetworkName=\nNetRefd=\nCANopenManager=1\nLSS_S"
  },
  {
    "path": "canopen_402_driver/test/test_driver_component.cpp",
    "chars": 2222,
    "preview": "//    Copyright 2023 Christoph Hellmann Santos\n//\n// This program is free software: you can redistribute it and/or modif"
  },
  {
    "path": "canopen_base_driver/CHANGELOG.rst",
    "chars": 2630,
    "preview": "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nChangelog for package canopen_base_driver\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"
  },
  {
    "path": "canopen_base_driver/CMakeLists.txt",
    "chars": 4615,
    "preview": "cmake_minimum_required(VERSION 3.8)\nproject(canopen_base_driver)\n\nif(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID M"
  },
  {
    "path": "canopen_base_driver/LICENSE",
    "chars": 11355,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "canopen_base_driver/include/canopen_base_driver/base_driver.hpp",
    "chars": 1701,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_base_driver/include/canopen_base_driver/diagnostic_collector.hpp",
    "chars": 4894,
    "preview": "// Copyright 2023 ROS-Industrial\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not us"
  },
  {
    "path": "canopen_base_driver/include/canopen_base_driver/lely_driver_bridge.hpp",
    "chars": 24427,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_base_driver/include/canopen_base_driver/lifecycle_base_driver.hpp",
    "chars": 1660,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_base_driver/include/canopen_base_driver/node_interfaces/node_canopen_base_driver.hpp",
    "chars": 4237,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_base_driver/include/canopen_base_driver/node_interfaces/node_canopen_base_driver_impl.hpp",
    "chars": 14686,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_base_driver/include/canopen_base_driver/visibility_control.h",
    "chars": 1913,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_base_driver/package.xml",
    "chars": 963,
    "preview": "<?xml version=\"1.0\"?>\n<?xml-model href=\"http://download.ros.org/schema/package_format3.xsd\" schematypens=\"http://www.w3."
  },
  {
    "path": "canopen_base_driver/src/base_driver.cpp",
    "chars": 1155,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_base_driver/src/lely_driver_bridge.cpp",
    "chars": 16302,
    "preview": "//   Copyright 2022 Christoph Hellmann Santos\n//\n//   Licensed under the Apache License, Version 2.0 (the \"License\");\n//"
  },
  {
    "path": "canopen_base_driver/src/lifecycle_base_driver.cpp",
    "chars": 1219,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_base_driver/src/node_interfaces/node_canopen_base_driver.cpp",
    "chars": 1068,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_base_driver/test/CMakeLists.txt",
    "chars": 1341,
    "preview": "ament_add_gtest(test_node_canopen_base_driver_ros\ntest_node_canopen_base_driver_ros.cpp\n)\ntarget_include_directories(tes"
  },
  {
    "path": "canopen_base_driver/test/master.dcf",
    "chars": 10148,
    "preview": "[DeviceComissioning]\nNodeID=1\nNodeName=\nNodeRefd=\nBaudrate=1000\nNetNumber=1\nNetworkName=\nNetRefd=\nCANopenManager=1\nLSS_S"
  },
  {
    "path": "canopen_base_driver/test/test_base_driver_component.cpp",
    "chars": 2157,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_base_driver/test/test_node_canopen_base_driver_ros.cpp",
    "chars": 3423,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_core/CHANGELOG.rst",
    "chars": 2274,
    "preview": "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nChangelog for package canopen_core\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n0.2.9 (2024-04"
  },
  {
    "path": "canopen_core/CMakeLists.txt",
    "chars": 4460,
    "preview": "cmake_minimum_required(VERSION 3.5)\nproject(canopen_core)\n\n# Default to C99\nif(NOT CMAKE_C_STANDARD)\n  set(CMAKE_C_STAND"
  },
  {
    "path": "canopen_core/ConfigExtras.cmake",
    "chars": 642,
    "preview": "#   Copyright (c) 2023 Vishnuprasad Prachandabhanu\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n#"
  },
  {
    "path": "canopen_core/LICENSE",
    "chars": 11355,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "canopen_core/include/canopen_core/configuration_manager.hpp",
    "chars": 3171,
    "preview": "//    Copyright 2022 Harshavadan Deshpande\n//                   Christoph Hellmann Santos\n//\n//    Licensed under the Ap"
  },
  {
    "path": "canopen_core/include/canopen_core/device_container.hpp",
    "chars": 10821,
    "preview": "//    Copyright 2022 Harshavadan Deshpande\n//                   Christoph Hellmann Santos\n//\n//    Licensed under the Ap"
  },
  {
    "path": "canopen_core/include/canopen_core/device_container_error.hpp",
    "chars": 1107,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_core/include/canopen_core/driver_error.hpp",
    "chars": 1046,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_core/include/canopen_core/driver_node.hpp",
    "chars": 10091,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_core/include/canopen_core/exchange.hpp",
    "chars": 3986,
    "preview": "//    Copyright 2022 Harshavadan Deshpande\n//                   Christoph Hellmann Santos\n//\n//    Licensed under the Ap"
  },
  {
    "path": "canopen_core/include/canopen_core/lifecycle_manager.hpp",
    "chars": 9458,
    "preview": "//    Copyright 2022 Harshavadan Deshpande\n//                   Christoph Hellmann Santos\n//\n//    Licensed under the Ap"
  },
  {
    "path": "canopen_core/include/canopen_core/master_error.hpp",
    "chars": 1027,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_core/include/canopen_core/master_node.hpp",
    "chars": 10166,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_core/include/canopen_core/node_interfaces/node_canopen_driver.hpp",
    "chars": 11162,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_core/include/canopen_core/node_interfaces/node_canopen_driver_interface.hpp",
    "chars": 3099,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_core/include/canopen_core/node_interfaces/node_canopen_master.hpp",
    "chars": 11145,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_core/include/canopen_core/node_interfaces/node_canopen_master_interface.hpp",
    "chars": 2665,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_core/include/canopen_core/visibility_control.h",
    "chars": 1758,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_core/launch/canopen.launch.py",
    "chars": 3373,
    "preview": "#    Copyright 2022 Christoph Hellmann Santos\n#\n#    Licensed under the Apache License, Version 2.0 (the \"License\");\n#  "
  },
  {
    "path": "canopen_core/package.xml",
    "chars": 898,
    "preview": "<?xml version=\"1.0\"?>\n<?xml-model href=\"http://download.ros.org/schema/package_format3.xsd\" schematypens=\"http://www.w3."
  },
  {
    "path": "canopen_core/readme.md",
    "chars": 2848,
    "preview": "# ROS2 canopen {#mainpage}\n\nWelcome to the ROS2 canopen documentation.\n\n## About\nROS2 CANopen is being developed and mai"
  },
  {
    "path": "canopen_core/scripts/setup_vcan.sh",
    "chars": 67,
    "preview": "modprobe vcan\nip link add dev vcan0 type vcan\nip link set up vcan0\n"
  },
  {
    "path": "canopen_core/src/configuration_manager.cpp",
    "chars": 1775,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_core/src/device_container.cpp",
    "chars": 17932,
    "preview": "//    Copyright 2022 Harshavadan Deshpande\n//                   Christoph Hellmann Santos\n//\n//    Licensed under the Ap"
  },
  {
    "path": "canopen_core/src/device_container_error.cpp",
    "chars": 877,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_core/src/device_container_node.cpp",
    "chars": 1186,
    "preview": "//    Copyright 2022 Harshavadan Deshpande\n//                   Christoph Hellmann Santos\n//\n//    Licensed under the Ap"
  },
  {
    "path": "canopen_core/src/driver_error.cpp",
    "chars": 857,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_core/src/driver_node.cpp",
    "chars": 3924,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_core/src/lifecycle_manager.cpp",
    "chars": 10787,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_core/src/master_error.cpp",
    "chars": 858,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_core/src/master_node.cpp",
    "chars": 2977,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_core/src/node_interfaces/node_canopen_driver.cpp",
    "chars": 3959,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_core/src/node_interfaces/node_canopen_master.cpp",
    "chars": 875,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_core/test/CMakeLists.txt",
    "chars": 4054,
    "preview": "ament_add_gmock(test_node_canopen_driver\n    test_node_canopen_driver.cpp\n)\ntarget_include_directories(test_node_canopen"
  },
  {
    "path": "canopen_core/test/bus_configs/bad_driver_duplicate.yml",
    "chars": 375,
    "preview": "---\nproxy_device_1:\n  node_id: 2\n  dcf: \"simple.eds\"\n  dcf_path: \"install/canopen_tests/share/canopen_tests/config/simpl"
  },
  {
    "path": "canopen_core/test/bus_configs/bad_driver_no_driver.yml",
    "chars": 149,
    "preview": "---\nproxy_device_1:\n  node_id: 2\n  dcf: \"simple.eds\"\n  dcf_path: \"install/canopen_tests/share/canopen_tests/config/simpl"
  },
  {
    "path": "canopen_core/test/bus_configs/bad_driver_no_id.yml",
    "chars": 176,
    "preview": "---\nproxy_device_1:\n  dcf: \"simple.eds\"\n  dcf_path: \"install/canopen_tests/share/canopen_tests/config/simple\"\n  driver: "
  },
  {
    "path": "canopen_core/test/bus_configs/bad_driver_no_package.yml",
    "chars": 163,
    "preview": "---\nproxy_device_1:\n  node_id: 2\n  dcf: \"simple.eds\"\n  dcf_path: \"install/canopen_tests/share/canopen_tests/config/simpl"
  },
  {
    "path": "canopen_core/test/bus_configs/bad_master_no_driver.yml",
    "chars": 51,
    "preview": "---\nmaster:\n  node_id: 1\n  package: \"canopen_core\"\n"
  },
  {
    "path": "canopen_core/test/bus_configs/bad_master_no_id.yml",
    "chars": 78,
    "preview": "---\nmaster:\n  driver: \"ros2_canopen::CanopenMaster\"\n  package: \"canopen_core\"\n"
  },
  {
    "path": "canopen_core/test/bus_configs/bad_master_no_package.yml",
    "chars": 65,
    "preview": "---\nmaster:\n  node_id: 1\n  driver: \"ros2_canopen::CanopenMaster\"\n"
  },
  {
    "path": "canopen_core/test/bus_configs/bad_no_master.yml",
    "chars": 375,
    "preview": "---\nproxy_device_1:\n  node_id: 2\n  dcf: \"simple.eds\"\n  dcf_path: \"install/canopen_tests/share/canopen_tests/config/simpl"
  },
  {
    "path": "canopen_core/test/bus_configs/good_driver.yml",
    "chars": 189,
    "preview": "---\nproxy_device_1:\n  node_id: 2\n  dcf: \"simple.eds\"\n  dcf_path: \"install/canopen_tests/share/canopen_tests/config/simpl"
  },
  {
    "path": "canopen_core/test/bus_configs/good_master.yml",
    "chars": 91,
    "preview": "---\nmaster:\n  node_id: 1\n  driver: \"ros2_canopen::CanopenMaster\"\n  package: \"canopen_core\"\n"
  },
  {
    "path": "canopen_core/test/bus_configs/good_master_and_two_driver.yml",
    "chars": 463,
    "preview": "---\nmaster:\n  node_id: 1\n  driver: \"ros2_canopen::CanopenMaster\"\n  package: \"canopen_core\"\n\nproxy_device_1:\n  node_id: 2"
  },
  {
    "path": "canopen_core/test/master.dcf",
    "chars": 10148,
    "preview": "[DeviceComissioning]\nNodeID=1\nNodeName=\nNodeRefd=\nBaudrate=1000\nNetNumber=1\nNetworkName=\nNetRefd=\nCANopenManager=1\nLSS_S"
  },
  {
    "path": "canopen_core/test/simple.eds",
    "chars": 3914,
    "preview": "[DeviceInfo]\nVendorName=Lely Industries N.V.\nVendorNumber=0x00000360\nProductName=\nProductNumber=0x00000000\nRevisionNumbe"
  },
  {
    "path": "canopen_core/test/test_canopen_driver.cpp",
    "chars": 3531,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_core/test/test_canopen_master.cpp",
    "chars": 3183,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_core/test/test_device_container.cpp",
    "chars": 36088,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_core/test/test_errors.cpp",
    "chars": 1371,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_core/test/test_lifecycle_canopen_driver.cpp",
    "chars": 4264,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_core/test/test_lifecycle_canopen_master.cpp",
    "chars": 3925,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_core/test/test_lifecycle_manager.cpp",
    "chars": 16275,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_core/test/test_node_canopen_driver.cpp",
    "chars": 12754,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_core/test/test_node_canopen_master.cpp",
    "chars": 18185,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_fake_slaves/CHANGELOG.rst",
    "chars": 3006,
    "preview": "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nChangelog for package canopen_fake_slaves\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"
  },
  {
    "path": "canopen_fake_slaves/CMakeLists.txt",
    "chars": 2830,
    "preview": "cmake_minimum_required(VERSION 3.8)\nproject(canopen_fake_slaves)\n\nif(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID M"
  },
  {
    "path": "canopen_fake_slaves/LICENSE",
    "chars": 11358,
    "preview": "\n                                 Apache License\n                           Version 2.0, January 2004\n                  "
  },
  {
    "path": "canopen_fake_slaves/Readme.md",
    "chars": 230,
    "preview": "# CANopen Mock Slaves\n\n## Motion Controller Slaves\n\nSupported modes:\n* Cyclic Position\n* Profiled Position (Thanks to mo"
  },
  {
    "path": "canopen_fake_slaves/config/cia402_slave.eds",
    "chars": 23170,
    "preview": "[DeviceInfo]\r\nVendorName=ROS-Industrial\r\nVendorNumber=0x555\r\nProductName=CIA402VTD\r\nBaudRate_10=0\r\nBaudRate_20=1\r\nBaudRa"
  },
  {
    "path": "canopen_fake_slaves/config/simple_slave.eds",
    "chars": 3914,
    "preview": "[DeviceInfo]\nVendorName=Lely Industries N.V.\nVendorNumber=0x00000360\nProductName=\nProductNumber=0x00000000\nRevisionNumbe"
  },
  {
    "path": "canopen_fake_slaves/include/canopen_fake_slaves/base_slave.hpp",
    "chars": 3442,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_fake_slaves/include/canopen_fake_slaves/basic_slave.hpp",
    "chars": 7524,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_fake_slaves/include/canopen_fake_slaves/cia402_slave.hpp",
    "chars": 29216,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_fake_slaves/include/canopen_fake_slaves/motion_generator.hpp",
    "chars": 4235,
    "preview": "// Copyright 2023 ROS-Industrial\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not us"
  },
  {
    "path": "canopen_fake_slaves/launch/basic_slave.launch.py",
    "chars": 3880,
    "preview": "#    Copyright 2022 Christoph Hellmann Santos\n#\n#    Licensed under the Apache License, Version 2.0 (the \"License\");\n#  "
  },
  {
    "path": "canopen_fake_slaves/launch/cia402_slave.launch.py",
    "chars": 3881,
    "preview": "#    Copyright 2022 Christoph Hellmann Santos\n#\n#    Licensed under the Apache License, Version 2.0 (the \"License\");\n#  "
  },
  {
    "path": "canopen_fake_slaves/package.xml",
    "chars": 711,
    "preview": "<?xml version=\"1.0\"?>\n<?xml-model href=\"http://download.ros.org/schema/package_format3.xsd\" schematypens=\"http://www.w3."
  },
  {
    "path": "canopen_fake_slaves/src/basic_slave.cpp",
    "chars": 1118,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_fake_slaves/src/cia402_slave.cpp",
    "chars": 1031,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_fake_slaves/src/motion_generator.cpp",
    "chars": 5819,
    "preview": "//    Copyright 2022 Christoph Hellmann Santos\n//\n//    Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "canopen_interfaces/CHANGELOG.rst",
    "chars": 810,
    "preview": "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nChangelog for package canopen_interfaces\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"
  },
  {
    "path": "canopen_interfaces/CMakeLists.txt",
    "chars": 1150,
    "preview": "cmake_minimum_required(VERSION 3.8)\nproject(canopen_interfaces)\n\nif(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MA"
  },
  {
    "path": "canopen_interfaces/LICENSE",
    "chars": 11355,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "canopen_interfaces/msg/COData.msg",
    "chars": 40,
    "preview": "uint16 index\nuint8 subindex\nuint32 data\n"
  },
  {
    "path": "canopen_interfaces/package.xml",
    "chars": 827,
    "preview": "<?xml version=\"1.0\"?>\n<?xml-model href=\"http://download.ros.org/schema/package_format3.xsd\" schematypens=\"http://www.w3."
  },
  {
    "path": "canopen_interfaces/srv/COHeartbeatID.srv",
    "chars": 52,
    "preview": "uint8 nodeid\nuint16  heartbeat #ms\n---\nbool success\n"
  },
  {
    "path": "canopen_interfaces/srv/CONmtID.srv",
    "chars": 47,
    "preview": "uint8 nmtcommand\nuint8 nodeid\n---\nbool success\n"
  },
  {
    "path": "canopen_interfaces/srv/CONode.srv",
    "chars": 30,
    "preview": "uint8 nodeid\n---\nbool success\n"
  },
  {
    "path": "canopen_interfaces/srv/CORead.srv",
    "chars": 57,
    "preview": "uint16 index\nuint8 subindex\n---\nbool success\nuint32 data\n"
  },
  {
    "path": "canopen_interfaces/srv/COReadID.srv",
    "chars": 355,
    "preview": "uint8 CANOPEN_DATATYPE_INT8 = 0x02\nuint8 CANOPEN_DATATYPE_INT16 = 0x03\nuint8 CANOPEN_DATATYPE_INT32 = 0x04\nuint8 CANOPEN"
  },
  {
    "path": "canopen_interfaces/srv/COTargetDouble.srv",
    "chars": 32,
    "preview": "float64 target\n---\nbool success\n"
  },
  {
    "path": "canopen_interfaces/srv/COWrite.srv",
    "chars": 57,
    "preview": "uint16 index\nuint8 subindex\nuint32 data\n---\nbool success\n"
  },
  {
    "path": "canopen_interfaces/srv/COWriteID.srv",
    "chars": 354,
    "preview": "uint8 CANOPEN_DATATYPE_INT8 = 0x02\nuint8 CANOPEN_DATATYPE_INT16 = 0x03\nuint8 CANOPEN_DATATYPE_INT32 = 0x04\nuint8 CANOPEN"
  },
  {
    "path": "canopen_master_driver/CHANGELOG.rst",
    "chars": 1384,
    "preview": "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nChangelog for package canopen_master_driver\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"
  },
  {
    "path": "canopen_master_driver/CMakeLists.txt",
    "chars": 4297,
    "preview": "cmake_minimum_required(VERSION 3.8)\nproject(canopen_master_driver)\n\nif(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID"
  },
  {
    "path": "canopen_master_driver/LICENSE",
    "chars": 11358,
    "preview": "\n                                 Apache License\n                           Version 2.0, January 2004\n                  "
  },
  {
    "path": "canopen_master_driver/include/canopen_master_driver/lely_master_bridge.hpp",
    "chars": 5279,
    "preview": "//    Copyright 2022 Harshavadan Deshpande\n//                   Christoph Hellmann Santos\n//\n//    Licensed under the Ap"
  },
  {
    "path": "canopen_master_driver/include/canopen_master_driver/lifecycle_master_driver.hpp",
    "chars": 1448,
    "preview": "//    Copyright 2022 Harshavadan Deshpande\n//                   Christoph Hellmann Santos\n//\n//    Licensed under the Ap"
  },
  {
    "path": "canopen_master_driver/include/canopen_master_driver/master_driver.hpp",
    "chars": 1313,
    "preview": "//    Copyright 2022 Harshavadan Deshpande\n//                   Christoph Hellmann Santos\n//\n//    Licensed under the Ap"
  },
  {
    "path": "canopen_master_driver/include/canopen_master_driver/node_interfaces/node_canopen_basic_master.hpp",
    "chars": 3029,
    "preview": "//    Copyright 2022 Harshavadan Deshpande\n//                   Christoph Hellmann Santos\n//\n//    Licensed under the Ap"
  },
  {
    "path": "canopen_master_driver/include/canopen_master_driver/node_interfaces/node_canopen_basic_master_impl.hpp",
    "chars": 4895,
    "preview": "//    Copyright 2022 Harshavadan Deshpande\n//                   Christoph Hellmann Santos\n//\n//    Licensed under the Ap"
  },
  {
    "path": "canopen_master_driver/include/canopen_master_driver/visibility_control.h",
    "chars": 1916,
    "preview": "// Copyright 2023 ROS-Industrial\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not us"
  },
  {
    "path": "canopen_master_driver/package.xml",
    "chars": 863,
    "preview": "<?xml version=\"1.0\"?>\n<?xml-model href=\"http://download.ros.org/schema/package_format3.xsd\" schematypens=\"http://www.w3."
  },
  {
    "path": "canopen_master_driver/src/lely_master_bridge.cpp",
    "chars": 4267,
    "preview": "//    Copyright 2022 Harshavadan Deshpande\n//                   Christoph Hellmann Santos\n//\n//    Licensed under the Ap"
  },
  {
    "path": "canopen_master_driver/src/lifecycle_master_driver.cpp",
    "chars": 1195,
    "preview": "//    Copyright 2022 Harshavadan Deshpande\n//                   Christoph Hellmann Santos\n//\n//    Licensed under the Ap"
  },
  {
    "path": "canopen_master_driver/src/master_driver.cpp",
    "chars": 1258,
    "preview": "//    Copyright 2022 Harshavadan Deshpande\n//                   Christoph Hellmann Santos\n//\n//    Licensed under the Ap"
  },
  {
    "path": "canopen_master_driver/src/node_interfaces/node_canopen_basic_master.cpp",
    "chars": 1078,
    "preview": "//    Copyright 2022 Harshavadan Deshpande\n//                   Christoph Hellmann Santos\n//\n//    Licensed under the Ap"
  }
]

// ... and 140 more files (download for full content)

About this extraction

This page contains the full source code of the ros-industrial/ros2_canopen GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 340 files (1.5 MB), approximately 435.4k tokens, and a symbol index with 859 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!