diff --git a/.clang-format b/.clang-format
new file mode 100644
index 00000000..10dd2c7c
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,16 @@
+---
+Language: Cpp
+BasedOnStyle: Google
+
+ColumnLimit: 100
+AccessModifierOffset: -2
+AlignAfterOpenBracket: AlwaysBreak
+BreakBeforeBraces: Allman
+ConstructorInitializerIndentWidth: 0
+ContinuationIndentWidth: 2
+DerivePointerAlignment: false
+PointerAlignment: Middle
+ReflowComments: true
+IncludeBlocks: Preserve
+InsertBraces: true
+...
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
new file mode 100644
index 00000000..32ff262c
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -0,0 +1,80 @@
+name: "Bug Report"
+description: Create a new ticket for a bug.
+title: "[BUG] -
"
+labels: [
+ "bug"
+]
+body:
+ - type: textarea
+ id: description
+ attributes:
+ label: "Description"
+ description: Please enter an explicit description of your issue
+ placeholder: Describe your issue in a few sentences
+ validations:
+ required: true
+ - type: dropdown
+ id: robot-os
+ attributes:
+ label: "KUKA robot OS"
+ description: Version of the KUKA OS are you using
+ multiple: true
+ options:
+ - KSS
+ - Sunrise
+ - iiQKA
+ - type: input
+ id: os-version
+ attributes:
+ label: "KUKA robot OS version"
+ description: Version of the KUKA robot OS
+ placeholder: eg. KSS 8.6
+ validations:
+ required: true
+ - type: input
+ id: if-version
+ attributes:
+ label: "KUKA external interface version"
+ description: Version of the KUKA external interface
+ placeholder: eg. RSI 4.1.3
+ validations:
+ required: true
+ - type: input
+ id: robot-model
+ attributes:
+ label: "Affected robot model(s)"
+ description: Robot model the issue came up with
+ placeholder: eg. KR10 R1100-2
+ validations:
+ required: true
+ - type: input
+ id: driver-version
+ attributes:
+ label: "Version or commit hash of the driver"
+ description: If the issue came up with an older version (not master), provide the release version or commit hash
+ validations:
+ required: false
+ - type: textarea
+ id: setup
+ attributes:
+ label: "Setup"
+ description: Describe your setup, launch files and executables started (optionally attach rqt_graph output), modifications to code
+ render: bash
+ validations:
+ required: true
+ - type: textarea
+ id: reprod
+ attributes:
+ label: "Reproduction steps"
+ description: Clear and ordered steps of reporoducing
+ render: bash
+ validations:
+ required: true
+ - type: textarea
+ id: logs
+ attributes:
+ label: "Logs"
+ description: Attach relevant log output here, mentioning if lines were omitted to help readability.
+ render: bash
+ validations:
+ required: false
diff --git a/.github/workflows/deploy_wiki.yml b/.github/workflows/deploy_wiki.yml
index 2b96f6a2..7976b57c 100644
--- a/.github/workflows/deploy_wiki.yml
+++ b/.github/workflows/deploy_wiki.yml
@@ -3,8 +3,9 @@ name: Deploy Wiki
on:
push:
paths:
- # Trigger only when wiki directory changes
+ # Trigger only when wiki directory or pipeline changes
- 'doc/wiki/**'
+ - '.github/workflows/deploy_wiki.yml'
branches:
# And only on master branch
- master
@@ -16,11 +17,8 @@ jobs:
- uses: actions/checkout@v2
- name: Push Wiki Changes
- uses: resizoltan/github-wiki-action@master
+ uses: SwiftDocOrg/github-wiki-publish-action@v1
+ with:
+ path: "doc/wiki"
env:
- # Make sure you have that / at the end. We use rsync
- # WIKI_DIR's default is wiki/
- WIKI_DIR: doc/wiki/
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- GH_MAIL: resizoltan@gmail.com
- GH_NAME: resizoltan
+ GH_PERSONAL_ACCESS_TOKEN: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}
diff --git a/.github/workflows/industrial_ci.yml b/.github/workflows/industrial_ci.yml
index 20a1d32c..242eb8bb 100644
--- a/.github/workflows/industrial_ci.yml
+++ b/.github/workflows/industrial_ci.yml
@@ -55,3 +55,14 @@ jobs:
# Run industrial_ci
- uses: 'kroshu/industrial_ci@master'
env: ${{ matrix.env }}
+ codespell:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-python@v4.7.1
+ with:
+ python-version: '3.10'
+ - run: pip install git+https://github.com/codespell-project/codespell.git
+ - uses: codespell-project/actions-codespell@v2
+ with:
+ check_filenames: true
diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml
new file mode 100644
index 00000000..2e1400f7
--- /dev/null
+++ b/.github/workflows/pre-commit.yml
@@ -0,0 +1,23 @@
+# This is a format job. Pre-commit has a first-party GitHub action, so we use
+# that: https://github.com/pre-commit/action
+
+name: Format
+
+on:
+ workflow_dispatch:
+ pull_request:
+
+jobs:
+ pre-commit:
+ name: Format
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-python@v4.7.1
+ with:
+ python-version: '3.10'
+ - name: Install system hooks
+ run: sudo apt install -qq cppcheck
+ - uses: pre-commit/action@v3.0.0
+ with:
+ extra_args: --all-files --hook-stage manual
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..c18dd8d8
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+__pycache__/
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 00000000..5631f349
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,140 @@
+
+# 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
+
+repos:
+ # Standard hooks
+ - repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: v4.4.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
+ - id: debug-statements
+ - id: end-of-file-fixer
+ - id: mixed-line-ending
+ - id: trailing-whitespace
+ exclude_types: [rst]
+ - id: fix-byte-order-marker
+
+
+ # Python hooks
+ - repo: https://github.com/asottile/pyupgrade
+ rev: v3.4.0
+ hooks:
+ - id: pyupgrade
+ args: [--py36-plus]
+
+ # PyDocStyle
+ - repo: https://github.com/PyCQA/pydocstyle
+ rev: 6.3.0
+ hooks:
+ - id: pydocstyle
+ args: ["--ignore=D100,D101,D102,D103,D104,D105,D106,D107,D203,D212,D404"]
+
+ - repo: https://github.com/psf/black
+ rev: 23.3.0
+ hooks:
+ - id: black
+ args: ["--line-length=99"]
+
+ - repo: https://github.com/pycqa/flake8
+ rev: 6.0.0
+ hooks:
+ - id: flake8
+ args: ["--extend-ignore=E501"]
+
+ # CPP hooks
+ - repo: https://github.com/pre-commit/mirrors-clang-format
+ rev: v15.0.6
+ hooks:
+ - id: clang-format
+ exclude: .*/fri_client_sdk/.*|.*/mock/.*|.*/robot_application/.*
+
+
+ - repo: local
+ hooks:
+ - id: ament_cppcheck
+ name: ament_cppcheck
+ exclude: .*/fri_client_sdk/.*|.*/mock/.*
+ description: Static code analysis of C/C++ files.
+ stages: [commit]
+ entry: env AMENT_CPPCHECK_ALLOW_SLOW_VERSIONS=TRUE ament_cppcheck
+ language: system
+ files: \.(h\+\+|h|hh|hxx|hpp|cuh|c|cc|cpp|cu|c\+\+|cxx|tpp|txx)$
+
+ # Maybe use https://github.com/cpplint/cpplint instead
+ - repo: local
+ hooks:
+ - id: ament_cpplint
+ name: ament_cpplint
+ exclude: .*/fri_client_sdk/.*|.*/mock/.*
+ description: Static code analysis of C/C++ files.
+ stages: [commit]
+ entry: ament_cpplint
+ language: system
+ files: \.(h\+\+|h|hh|hxx|hpp|cuh|c|cc|cpp|cu|c\+\+|cxx|tpp|txx)$
+ args: ["--linelength=100", "--filter=-whitespace/newline"]
+
+ # 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$
+
+ # Copyright
+ - repo: local
+ hooks:
+ - id: ament_copyright
+ name: ament_copyright
+ exclude: .*/fri_client_sdk/.*|.*/mock/.*
+ description: Check if copyright notice is available in all files.
+ stages: [commit]
+ entry: ament_copyright
+ 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.4
+ hooks:
+ - id: codespell
+ args: ['--write-changes']
+ exclude: CHANGELOG\.rst|\.(svg|pyc)$
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index f651c41c..169fcf32 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,10 +1,34 @@
-The ROS2 KUKA Sunrise driver is being developed and maintained by the kroshu team, but everyone is welcome to contribute. Please take the following aspects into consideration when making contributions:
+## Issue tracking
-- By default the Git ["Fork and Branch"](https://blog.scottlowe.org/2015/01/27/using-fork-branch-git-workflow/) workflow should be followed.
-- To foster a high quality product, feature extensions and improvements shall be done after careful design choices. Therefore, design documents and discussion with the maintainers prior to any development is strongly encouraged to make sure that everyone agrees on the issue and the suggested solution. Depending on the individual case the way to do this could be through a GitHub issue, a pull request to the design drafts folder or a new discussion on the repository's Discussions forum.
-- Code quality in this repository is monitored via industrial_ci and SonarCloud. All changes must pass the checks performed by these. (There is some flexibility to test coverage)
+If you have questions, suggestions or found a bug, feel free to open an [issue](https://github.com/kroshu/kuka_drivers/issues).
+When filing an issue, please check open issues to make sure somebody else hasn't already reported it. Please try to include as much information as you can, including:
+- A reproducible test case or series of steps
+- The version/commit hash of our code being used
+- Any modifications you've made relevant to the bug
+- Anything unusual about your environment or deployment
+Please do not add labels to the issue, that should be handled by the maintainers.
+## Contributing
+
+Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that:
+
+- Your PR addresses only one issue
+- Your PR has a descriptive title and a short summary
+- All pipelines are green, including
+ - Industrial CI
+ - Sonarcloud
+ - Spell checks
+ - Linters
+
+To send us a pull request, please:
+- Discuss the proposed changes with the maintainers, preferably in an issue
+- Fork the repository
+- Modify the source focusing on the specific change you are contributing
+- Ensure that local tests pass (`colcon test` and `pre-commit` run)
+- Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation
+
+## Licensing
Any contribution that you make to this repository will
be under the Apache 2 License, as dictated by that
[license](http://www.apache.org/licenses/LICENSE-2.0.html):
@@ -18,4 +42,3 @@ be under the Apache 2 License, as dictated by that
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
~~~
-
diff --git a/README.md b/README.md
index 5fc60efe..d9fadb8f 100644
--- a/README.md
+++ b/README.md
@@ -1,14 +1,18 @@
# ROS2 KUKA Drivers
-Experimental ROS2 driver for KUKA robots. Recommended distribution is [ROS 2 Humble Hawksbill:](https://docs.ros.org/en/humble/Installation.html).
-
-> ROS2 Iron Irwini has breaking changes, thus it is not yet supported.
+This repository contains ROS2 drivers for all KUKA operating systems.
Github CI | SonarCloud
------------| ---------------
[](https://github.com/kroshu/ros2_kuka_sunrise_fri_driver/actions) | [](https://sonarcloud.io/dashboard?id=kroshu_kuka_drivers)
+# Requirements
+The drivers require a system with ROS installed. It is recommended to use Ubuntu 22.04 with ROS humble. Iron Irwini has breaking changes in the moveit API, thus it is not yet supported.
+It is also recommended to use a client machine with a real-time kernel, as all three drivers require cyclic, real-time communication. Due to the real-time requirement, Windows systems are not recommended and covered in the documentation.
+
+
# Installation
+The driver is not available as a binary package, building from source is necessary.
Create ROS2 workspace (if not already created).
```bash
@@ -49,6 +53,7 @@ Source built KUKA packages.
source ~/ros2_ws/install/setup.bash
```
-# Get Started
+# Getting Started
+Documentation of this project can be found on the repository's [Wiki](https://github.com/kroshu/kuka_drivers/wiki) page.
-Documentation of this project can be found on the repository's [Wiki](https://github.com/kroshu/kuka_drivers/wiki) page.
\ No newline at end of file
+If you find something confusing, not working, or would like to contribute, please read our [contributing guide](CONTRIBUTING.md) before opening an issue or creating a pull request.
diff --git a/doc/lego_project.drawio b/doc/lego_project.drawio
deleted file mode 100644
index efb6996a..00000000
--- a/doc/lego_project.drawio
+++ /dev/null
@@ -1 +0,0 @@
-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
\ No newline at end of file
diff --git a/doc/wiki/Home.md b/doc/wiki/Home.md
index 6b76fcda..535d960d 100644
--- a/doc/wiki/Home.md
+++ b/doc/wiki/Home.md
@@ -1,142 +1,117 @@
# Welcome to the ROS2 KUKA drivers project!
-## KUKA Sunrise driver (FRI)
+## Goals of the project
-### Project description
+This project aims to provide reliable real-time capable drivers for all KUKA robots. Currently KUKA robots are available with 3 different operating systems with real-time control API-s:
+- KSS supporting industrial robots, with Robot Sensor Interface (RSI)
+- Sunrise supporting cobots (LBR iiwa-s), with Fast Robot Interface (FRI)
+- iiQKA supporting cobots (LBR iisy-s), with ExternalAPI.Control (EAC)
-This project centers on the development of a comprehensive ROS2 driver for external control of KUKA robots running on Sunrise OS through the real-time Fast Robot Interface (FRI). The following aspects are given particular consideration:
+It is also the goal of this project to provide the same API for all three OS-s, hiding the underlying startup procedure and communication technology, thus enabling changing seamlessly to a different KUKA OS.
-1. Application lifecycle controlled completely from ROS2, e.g.
-
- - Parameter configuration
-
- - Start/stop of external monitoring and commanding
-
- - Reacting to application errors
+Additionally the aim was to write high quality, maintainable code with standardized interfaces, that conforms with the standards defined by the [ROS-Industrial project](https://www.rosin-project.eu/).
-2. Exposing all functionality of the FRI towards the ROS2 system, e.g.
-
- - All command and control modes of joints
-
- - Field bus I/O handling
+## Common interface
-3. Exploiting new features of ROS2 w.r.t. ROS1, e.g.
-
- - Lifecycle management
-
- - Node-based ROS parameters
-
- - Real-time inter-node communication
-
-### Current state of project
-
-This project is currently experimental. The functionalities are not fully tested and the API and the internal architecture of the driver should be expected to change. This wiki is targeted at developers who would like to understand and potentially contribute to the project. Usage of this driver is discouraged except for the testing of the driver, only in controlled environment and with the proper safety configuration applied.
-
-### Features
-
-The following features of the FRI are exposed to ROS2:
+Two different interfaces should be defined for all drivers supporting real-time control:
+- real-time interface, defining how to handle the cyclic dataflow
+- non-real-time interface, defining the startup procedure with optional configuration
#### Real-time interface
+The choice for the real-time interface was straightforward, as a standardized control framework exists for ROS2, called `ros2_control`, also supported by ROS-Industrial. The drivers are built using this framework, therefore it is recommended the read through its [documentation](https://control.ros.org/master/doc/ros2_control/doc/index.html), as this documentation builds on the knowledge of the framework.
-- [ ] Monitor joint states
- - [x] Actual position
- - [ ] Actual torque
- - [ ] Setpoint position
- - [ ] Setpoint torque
- - [x] External torque
-- [ ] Joint commands
- - [x] Position
- - [x] Torque
-- [ ] Field bus
- - [ ] Inputs
- - [ ] Outputs
-- [ ] Connection quality
-- [ ] Safety state
-- [x] Tracking performance
-
-#### Manager interface
-
-- [x] Session state
-- [x] Control mode
-- [x] Client command mode
-- [ ] Operation mode
-- [ ] Number of axes
-
-## KUKA KSS driver (RSI)
-
-Another project in the repo centers on the development of a ROS2 driver for KSS robots through Robot Sensor Interface (RSI). It is in an experimental state, with only joint angle states and commands available. The guide to set up this driver on a real robot can be found in kuka_kss_rsi_driver\krl for both KCR4 and KRC5 controllers.
-
-### Simulation
-
-To try out the driver with an open-loop simulation the driver and the kuka_rsi_simulator must be started, (at first only a "collapsed" robot will be visible in rviz):
-
-**`ros2 launch kuka_kss_rsi_driver startup_with_rviz.launch.py`**
-
-**`ros2 launch kuka_rsi_simulator kuka_rsi_simulator_launch.py`**
-
-After all components have started successfully, the system needs to be configured and activated to start the simulation, the robot will be visible in rviz after activation:
-
-**`ros2 lifecycle set robot_manager configure`**
-
-**`ros2 lifecycle set robot_manager activate`**
-
-## iiQKA driver (ECI)
-
-The third project in the repo is the driver for iiQKA robots.
-
-### Architecture
-
-The driver uses the ros2_control framework, so a variaty of controllers are supported and it can be easily integrated into moveit. It consists of a realtime component for controlling the robot via UDP (ROS2 hardware interface) and a non-realtime one for lifecycle management of the controllers and the hardware interface. The driver supports a control cycle time of 4 milliseconds, but the round-trip time of one cycle should not exceed 3 milliseconds, as above that the packets are considered lost. Therefore it is advised to run the driver on a realtime-capable Linux machine (with the PRREMPT_RT patch applied). After a few lost packets the connection is considered not stable enough and external control is ended.
-
-The driver depends on some KUKA-specific packages, which are only available with the real robot, but setting the MOCK_HW_ONLY flag in the hardware_interface enables the usage of the driver in a simulated way, so that motion planning problems can be tried out with the same components running.
-Two additional packages (not listed in package.xml) must be installed with apt:
-- libnanopb-dev
-- libgrpc++-dev
+All 3 of the KUKA real-time interfaces handle the timing on the controller side, so external control is always synchronized with the internal control cycle. This means, that calling the `read` method of the `controller_manager` cannot return immediately, but has to wait until the controller sends an update, which is triggered by the internal clock. Because of this blocking read, the default `ros2_control_node` cannot be used, as there it is expected that the `controller_manager` handles the timing according to the configured control frequency. Therefore a [custom control node](https://github.com/kroshu/kuka_drivers/blob/master/kuka_drivers_core/src/control_node.cpp) was implemented that uses the `controller_manager` and all other tools of `ros2_control`, but leaves the time management to the robot controller.
-### Setup
+This change does not influence the API of the `ros2_control` framework, the real-time dataflow can be accessed by any controller.
-By default, the mock libraries are used, this can be changed in the cmake file by setting MOCK_KUKA_LIBS to FALSE before building.
+#### Non-real-time interface
+The startup procedure for any system in ROS can be defined using a launch file, that can start multiple processes. By default, starting the control node with a hardware interface and controllers configured immediately starts external control. This behaviour has a few drawbacks:
+- The user cannot configure some parameters during runtime, that cannot be changed during external control
+- The user cannot easily synchronize the start of external control with other components of the system
+- It can cause unexpected behaviour, which can be potentially dangerous to the hardware or surroundings.
+ - In torque control mode, the robot can start to move, if the torque sensors are not perfectly calibrated (and as that is hard to achieve, this can happen in most cases). This could be mitigated with a simple torque controller that tries to hold the position, but there is no guarantee that loading and activating the controller was successful, external control would start even if it failed. This could result in a scenario, where the robot starts to move unexpectedly.
-The IP addresses of the client machine and controller must be given in the *config/driver_config.yaml* configuration file. A rebuild is not needed after the changes, but the file has to be modified before starting the nodes. The control mode of the robot can also be modified in the same configuration file: you can choose either 1 (POSITION_CONTROL), 3 (JOINT_IMPEDANCE_CONTROL) or 5 (TORQUE_CONTROL). This also sets the control_mode parameter of the robot manager node, which can be only modified at startup, control mode changes are not supported in runtime at the current state.
+The last issue should be certainly prevented from happening, therefore it was decided to extend the default startup procedure with a [lifecycle interface](https://design.ros2.org/articles/node_lifecycle.html), that synchronizes all components of the driver. The hardware interfaces and controllers already have a lifecycle interface, but by default they are loaded and activated at startup. This configuration was modified to only load the hardware interfaces and controllers, configuration and activation is handled by a custom a lifecycle node, called `robot_manager`. The 3 states of the `robot_manager` node have the following meaning:
-Besides, the setting of scheduling priorities must be allowed for your user (extend /etc/security/limits.conf with "username - rtprio 98" and restart) to enable real-time performance.
+- `unconfigured`: all necessary components are started, but no connection is needed to the robot
+- `configured`: The driver has configured the parameters necessary to start external control. Connection to the robot might be needed. (All of the parameters have default values in the driver, which are set on the robot controller during configuration.) A few [configuration controllers](https://github.com/kroshu/kuka_controllers?tab=readme-ov-file#configuration-controllers) might be active, that handle the runtime parameters of the hardware interface.
+- `active`: external control is running with cyclic real-time communication, controllers are active
-### Usage
+To achieve these synchronized states, the state transitions of the system do the following steps (implemented by the launch file and the `robot_manager` node):
+- startup: all components of the system are started: `control_node`, `robot_manager` node, `robot_state_publisher` (optionally `rviz`) and all of the necessary controllers are loaded and configured
+- `configure`: activate configuration controllers, configure hardware interface
+- `activate`: activate real-time controllers, activate hardware interface
+- `deactivate`: deactivate hardware interface, deactivate real-time controllers
+- `cleanup`: clean up hardware interface, deactivate configuration controllers
-The usage of the driver is quite simple, one has to start the launch file in the package to start all required nodes (it also starts an rviz node for visualisation, which can be commented out if not needed):
+Note: the lifecycle interface of the controllers are a little bit different, as they do not have a `cleanup` transition. To have a consequent `unconfigured` state, the configuration of the controllers are not handled in the `configure` transition, but at startup.
-**`ros2 launch kuka_iiqka_eac_driver startup.launch.py`**
+Including the controller state handling in the system state makes the implementation more complex, as controllers must be deactivated and activated at control mode changes, but it has two advantages:
+ - minor performance increase: unused controllers are not active and therefore do not consume resources
+ - unexpected behaviour is not possible: external control will not start on the robot, unless all necessary controllers are successfully activated, while control mode changes (on the robot) are only possible after the controllers for the new control mode are activated.
-After all components have started successfully, the system needs to be configured and activated to start external control:
+The consequence of the lifecycle interface is, that 3 commands are necessary to start external control for all robots:
+ - start the appropriate launch file for your robot with your robot model as parameter (details can be found [here](#detailed-setup-and-startup-instructions))
+ - `ros2 lifecycle set robot_manager configure`
+ - `ros2 lifecycle set robot_manager activate`
-**`ros2 lifecycle set robot_manager configure`**
+#### Control mode definitions
+The control mode specifications are also part of the common API. They are defined as an enum in the [`kuka_drivers_core`](https://github.com/kroshu/kuka_drivers/blob/master/kuka_drivers_core/include/kuka_drivers_core/control_mode.hpp) package, and have the following meaning:
-**`ros2 lifecycle set robot_manager activate`**
+- joint position control: the driver streams cyclic position updates for every joint.
+ - Needed command interface(s): `position`
+- joint impedance control: the driver streams cyclic position updates for every joint and additionally stiffness [Nm/rad] and normalized damping [-] attributes, which define how the joint reacts to external effects (around the setpoint position). The effect of gravity is compensated internally.
+ - Needed command interface(s): `position`, `stiffness`, `damping`
+- joint velocity control: the driver streams cyclic velocity updates for every joint.
+ - Needed command interface(s): `velocity`
+- joint torque control: the driver streams cyclic torque updates for every joint, which define the torque overlay to be superimposed over gravity compensation. (An input of 0 means, that the joint should remain in gravity compensatin and should not move.)
+ - Needed command interface(s): `effort`
+- cartesian position control: the driver streams cyclic pose updates for every degree of freedom. The orientation representation is the KUKA ABC convention. It is the responsibility of the user to stream poses, for which a valid IK solution exists.
+ - Needed command interface(s): `cart_position`
+- cartesian impedance control: the driver streams cyclic pose updates for every degree of freedom. Additional stiffness [N/m or Nm/rad] and normalized damping [-] attributes define the behaviour of each degree of freedom to external forces. The nullspace stiffness and damping values define the behaviour of the redundant degree(s) of freedom.
+ - Needed command interface(s): `cart_position`, `cart_stiffness`, `cart_damping`, (`nullspace_stiffness`, `nullspace_damping`)
+- cartesian velocity control: the driver streams cyclic cartesian velocity (twist) updates for every degree of freedom. It is the responsibility of the user to stream velocities, for which a valid IK solution exists.
+ - Needed command interface(s): `cart_velocity`
+- wrench control: the driver streams cyclic wrench updates, which define the forces and torques, that the robot end effector should exert on the environment. The effect of gravity is internally compensated. (If the environment does not have a counterforce, the robot will start to move)
+ - Needed command interface(s): `wrench`
-On successful activation the robot controller and the driver start communication with a 4 ms cycle time, and it is possible to move the robot through the joint trajectory controller. The easiest way to achieve this is to start an rqt_joint_trajcectory controller and move the joints with cursors or one can also execute trajectories planned with moveit - an example of this can be found in kuka_sunrise_fri_driver_control/iiqka_moveit_example package.
-To stop external control, the components have to be deactivated with **`ros2 lifecycle set robot_manager deactivate`**
+#### Supported features
+The following table shows the supported features and control modes of each driver. (`✓` means supported, `✗` means not supported by the KUKA interface, empty means supported by the KUKA interface, but not yet supported by the driver)
-BEWARE, that this is a non-realtime process including lifecycle management, so the connection is not terminated immediately, in cases where an abrupt stop is needed, the safety stop of the SmartPad should be used!
+|OS | Joint position control | Joint impedance control | Joint velocity control | Joint torque control | Cartesian position control | Cartesian impedance control | Cartesian velocity control | Wrench control| I/O control|
+|---|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
+|KSS| ✓ | ✗ | ✗ | ✗ | | ✗ | ✗ | ✗ | |
+|Sunrise| ✓ | ✓ | ✗ | ✓ | | | ✗ | | |
+|iiQKA| ✓ | ✓ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ |
-It is also possible to use different controllers with some modifications in the launch and yaml files (for example ForwardCommandController, which forwards the commands send to a ROS2 topic towards the robot). In these cases, one has to make sure, that the commands sent to the robot are close to the current position, otherwise the machine protection will stop the robot movement.
-### Issues
+## Additional packages
+The repository contains a few other packages aside from the 3 drivers:
+- `kuka_driver_interfaces`: this package contains the custom message definition necessary for KUKA robots.
+- `kuka_drivers_core`: this package contains core functionalities used by more drivers, including the `control_node`, base classes for nodes with improved parameter handling, enum and constant definitions and a class for managing the controller activation and deactivation at control mode changes. Details about these features can be found in the package [documentation](https://github.com/kroshu/kuka_drivers/blob/master/kuka_drivers_core/README.md)
+- `kuka_rsi_simulator`: this package contains a simple simulator of RSI, that implements a UDP server accepting the same xml format as RSI and returning the commanded values as the current state, without any checks.
+- `iiqka_moveit_example`: this package contains basic examples of using moveit with the driver, more information in the [next section](#moveit-integration). Additionally it contains a [launch file](../../examples/iiqka_moveit_example/launch/launch_trajectory_publisher.launch.py) that commands 4 goal positions near the home position cyclically (the points and parameters can be modified in [this](../../examples/iiqka_moveit_example/config/dummy_publisher.yaml) configuration file). This can be used to test moving any robot with the driver, and is the recommended way instead of the `rqt_joint_trajectory_controller`, which commands very jerky trajectories due to batching.
-The driver is in an experimental state, with only joint position commands supported. We have encountered the following isses:
-- If there is an error after starting the launch file, the process must be stopped and started again. This error is related to spawning the joint_trajectory controller and comes forth sporadically.
-The logs are the following:
+## Moveit integration
- [spawner-4] Node not found
+The `ros2_control` framework supports Moveit out-of-the-box, as the `joint_trajectory_controller` can interpolate the trajectories planned by it. Setting up Moveit is a little more complex, therefore an example package (`iiqka_moveit_example`) is provided to help developers.
- [ERROR] [spawner-4]: process has died [pid ..., exit code 1, cmd '/opt/ros/humble/lib/controller_manager/spawner joint_trajectory_controller -c /controller_manager -p .../kuka_iiqka_eac_driver/share/kuka_iiqka_eac_driver/config/joint_trajectory_controller_config.yaml --inactive --ros-args']
+The package contains a [launch file](../../examples/iiqka_moveit_example/launch/moveit_planning_example.launch.py) that starts the iiQKA driver, `rviz`, and the `move_group` server with the required configuration. The `robot_manager` lifecycle node should be configured and activated after startup.
-- If you activate and deactivate the robot manager node, the reactivation will fail, you must restart the whole process if you want to control the robot again
+After activation, the Motion Planning plugin can be added (`Add` -> `moveit_ros_visualisation` -> `MotionPlanning`) to plan trajectories from the `rviz` GUI. (`Planning group` in the `Planning` tab should be changed to `manipulator`.)
+The package also contains examples of sending planning requests from C++ code, in which case the `rviz` plugin is not necessary. The `MoveitExample` class implements a wrapper around the `MoveGroupInterface`, the example executables in the package use this class to interact with Moveit. Four examples are provided:
+- `moveit_basic_planners_example`: the example uses the `PILZ` motion planner to plan a `PTP` and a `LIN` trajectory. It also demonstrates that planning with collision avoidance is not possible with the `PILZ` planner by adding a collision box that invalidates the planned trajectory.
+- `moveit_collision_avoidance_example`: the example adds a collision box to the scene and demonstrates, that path planning with collision avoidance is possible using the `OMPL` planning pipeline.
+- `moveit_constrained_planning_example`: this example demonstrates constrained planning capabilities, as the planner can find a valid path around the obstacle with the end effector orientation remaining constant (with small tolerance).
+- `moveit_depalletizing_example`: this example shows a depalletizing example: a 3x3x3 pallet pattern is added to the scene, the robot can successfully finish the depalletizing process by attaching each pallet to the end effector and moving it to a dropoff position with collision avoidance.
+Note: the first three examples should be executed consequently (without restarting the launch file) to ensure that the collision objects are indeed in the way of the trivial path. The 4. example should be executed independently, so that the collision box added in the other examples are not there (launch file should be restarted after the other examples).
-## Contact
+Note: The examples need user interaction in `rviz`, the `Next` button (`RvizVisualToolsGui` tab) should be pressed each time the logs indicate it.
-If you have questions, suggestions or want to contribute, feel free to open an [issue](https://github.com/kroshu/ros2_kuka_sunrise_fri_driver/issues) or start a [discussion](https://github.com/kroshu/ros2_kuka_sunrise_fri_driver/discussions).
+## Detailed setup and startup instructions
+For more detailed information about the drivers, visit the dedicated wiki pages for [KSS](https://github.com/kroshu/kuka_drivers/wiki/KSS_RSI), [Sunrise](https://github.com/kroshu/kuka_drivers/wiki/Sunrise_FRI) or [iiQKA](https://github.com/kroshu/kuka_drivers/wiki/iiQKA_EAC) robots.
diff --git a/doc/wiki/KSS_RSI.md b/doc/wiki/KSS_RSI.md
new file mode 100644
index 00000000..7bb29a41
--- /dev/null
+++ b/doc/wiki/KSS_RSI.md
@@ -0,0 +1,151 @@
+## KSS driver (RSI)
+
+### Setup
+
+#### Client side
+It is recommended to use the driver on a real-time capable client machine (further information about setting up the PREEMPT_RT patch can be found [here](https://github.com/kroshu/kuka_drivers/wiki/Realtime)).
+
+To set up the controller with WorkVisual (which is necessary if RSI is not yet installed), a Windows machine is also required.
+
+##### Client IP configuration
+- Set a fixed IP in the subnet of the KLI interface for the Windows machine, which is required to connect to WorkVisual and transfer the project
+- Set a fixed IP in the subnet of the RSI interface for the real-time machine, which is required to send commands via the RSI interface.
+
+#### Controller side
+These instructions were tested with RSI 4.1.3 (on KSS8.6) and RSI 5.0.2 (on KSS8.7)
+
+##### Controller network configuration
+
+Windows runs behind the SmartHMI on the teach pad. Make sure that the **Windows interface** of the controller and the **PC with ROS** is connected to the same subnet.
+
+1. Log in as **Expert** or **Administrator** on the teach pad and navigate to **Network configuration** (**Start-up > Network configuration > Activate advanced configuration**).
+ There should already be an interface checked out as the **Windows interface**.
+ - **Windows interface checkbox** should be checked.
+2. Add a new network for RSI:
+
+ **KRC4:**
+ - Minimize the SmartHMI (**Start-up > Service > Minimize HMI**).
+ - Run **RSI-Network** from the Windows Start menu (**All Programs > RSI-Network**).
+ - Check that the **Network - Kuka User Interface** shows the Windows interface with the specified IP address.
+ - Add a new IP address on another subnet for the **RSI interface**.
+ - Select the entry **New** under **RSI Ethernet** in the tree structure and press **Edit**.
+ - Enter the IP address and confirm with **OK**.
+ - Close **RSI-Network** and maximize the SmartHMI.
+
+ **KRC5:**
+ - Press the **Advanced** button and **New interface**.
+ - Select **Mixed IP address** and keep the default **Receiving task: Target subnet** and **Real-time receiving Task: UDP**
+ - Set the IP address to a different subnet then the **KLI interface**.
+ - **Default gateway**: leave it empty
+ - **Windows interface checkbox** should NOT be checked
+
+3. Reboot the controller with a cold restart (**Shutdown > Check *Force cold start* and *Reload files* > Reboot control PC**).
+
+##### Update and upload configuration files
+There are 3 files necessary for RSI that are available in the `krl` directory:
+
+- `ros_rsi_ethernet.xml`: specifies the data transferred via RSI and contains the IP configuration of the client machine:
+ - The `IP_NUMBER` tag should be modified so that it corresponds to the IP address previously added for your (real-time) PC.
+ - The `PORT` might be left as it is (59152), but can be also changed if a different port is to be used on the client machine.
+
+- `ros_rsi.src`: This contains the KRL program that starts external control and should not be modified.
+- `ros_rsi.rsix`: This contains the RSI context (can be visualized with **RSIVisual**). It can be modified for example to add filtering behaviour, but this is not recommended and should be implemented on the client side instead.
+ - For older RSI versions (<=4.0.3), the context can only be defined in 3 different files: `ros_rsi.rsi.xml`, `ros_rsi.rsi.diagram` and `ros_rsi.rsi`, these can be found under `krl/deprecated`. In this case, these 3 files should be copied to the controller instead of the `ros_rsi.rsix`.
+
+There are two options to upload these files to the controller:
+
+Method 1:
+1. Copy the files to a USB-stick.
+2. Plug it into the teach pad or controller.
+3. Log in as **Expert** or **Administrator** on the controller.
+4. Copy the `ros_rsi.src` file to `KRC:\R1\Program`.
+5. Copy the rest of the files to `C:\KRC\ROBOTER\Config\User\Common\SensorInterface`.
+
+Method 2:
+1. Connect to the KRC with WorkVisual
+2. Log in as **Expert** or **Administrator** on the controller.
+4. Copy the `ros_rsi.src` file to `KRC:\R1\Program` in WorkVisual
+5. Copy the rest of the files to `C:\KRC\ROBOTER\Config\User\Common\SensorInterface` in WorkVisual
+6. Deploy the project
+
+### Configuration
+
+#### Startup configuration
+
+The following configuration files are available in the `config` directory of the package:
+- `driver_config.yaml`: contains the IP address of the client machine
+- `ros2_controller_config.yaml`: contains the controller types for every controller name. Should be only modified if a different controller is to be used. The `configure_components_on_start` parameter should never be modified, which ensures that the hardware interface is not activated at startup.
+- configuration files for specific controllers, for further information, see the documentation of the given controller
+
+##### IP configuration
+The following parameters must be set in the driver configuration file:
+- `client_ip`: IP address of the client machine, should be identical to the one set in `ros_rsi_ethernet.xml`
+- `client_port`: port of the real-time communication on the client machine, should be identical to the one set in `ros_rsi_ethernet.xml`
+
+#### Runtime parameters
+
+The KSS driver currently does not have runtime parameters. Control mode cannot be changed if the driver is running, as that also requires modifying the RSI context on the controller.
+
+### Usage
+
+#### Starting the driver
+
+1. To start the driver, two launch file are available, with and without `rviz`. To launch (without `rviz`), run:
+ ```
+ ros2 launch kuka_kss_rsi_driver startup.launch.py
+ ```
+ - This starts the 3 core components of every driver (described in the *Non-real-time interface* section of the [project overview](Project%20overview.md)) and the following controllers:
+ - `joint_state_broadcaster` (no configuration file, all state interfaces are published)
+ - `joint_trajectory_controller` ([configuration file](../../kuka_kss_rsi_driver/config/joint_trajectory_controller_config.yaml))
+
+ - After successful startup, the `robot_manager` node has to be activated to start the cyclic communication with the robot controller, see further steps (before this only a collapsed robot is visible in `rviz`):
+
+2. Configure and activate all components the driver:
+ ```
+ ros2 lifecycle set robot_manager configure
+ ros2 lifecycle set robot_manager activate
+ ```
+ - The hardware interface is now waiting for the robot controller to connect, the timeout for this is currently 10 seconds
+3. Start the `KRC:\R1\Program\ros_rsi.src` program on the controller and execute the line of `RSI_MOVECORR()`
+ - in T1, a warning (*!!! Attention - Sensor correction goes active !!!*) should be visible after reaching `RSI_MOVECORR()`, which should be confirmed to start this step
+
+On successful activation the brakes of the robot will be released and external control is started. To test moving the robot, the `rqt_joint_trajectory_controller` is not recommended, use the launch file in the `iiqka_moveit_example` package instead (usage is described in the *Additional packages* section of the [project overview](Project%20overview.md)).
+
+
+##### Launch arguments
+
+Both launch files support the following arguments:
+- `robot_model` and `robot_family`: defines which robot to use. The available options for the valid model and family combinations can be found in the [readme](https://github.com/kroshu/kuka_robot_descriptions?tab=readme-ov-file#what-data-is-verified) of the `kuka_robot_descriptions` repository.
+- `use_fake_hardware`: if true, the `mock_components/GenericSystem` will be used instead of the `KukaRSIHardwareInterface`. This enables trying out the driver without actual hardware.
+
+#### Stopping external control
+
+To stop external control, all components have to be deactivated with `ros2 lifecycle set robot_manager deactivate`
+
+BEWARE, that this is a non-realtime process including lifecycle management, so the connection is not terminated immediately, in cases where an abrupt stop is needed, the safety stop of the Teach Pendant should be used!
+
+
+### Simulation
+
+To try out the driver with an open-loop simulation, the driver and the `kuka_rsi_simulator` must be started, (before activation only a "collapsed" robot will be visible in `rviz`):
+
+```
+ros2 launch kuka_kss_rsi_driver startup_with_rviz.launch.py
+```
+
+```
+ros2 launch kuka_rsi_simulator kuka_rsi_simulator_launch.py
+```
+
+After all components have started successfully, the system needs to be configured and activated to start the simulation. The robot will be visible in rviz after activation:
+
+```
+ros2 lifecycle set robot_manager configure
+ros2 lifecycle set robot_manager activate
+```
+
+### Known issues and limitations
+
+- There are currently heap allocations in the control loop (hardware interface `read()` and `write()` functions), therefore the driver is not real-time safe
+- In case of an error on the controller side, the driver is not deactivated
+- Cartesian position control mode and I/O-s not yet supported
diff --git a/doc/wiki/Realtime.md b/doc/wiki/Realtime.md
new file mode 100644
index 00000000..0d8d7f53
--- /dev/null
+++ b/doc/wiki/Realtime.md
@@ -0,0 +1,123 @@
+## Setting up the real-time patch
+
+### Prerequisites:
+- at least 30GB free disk space.
+
+### Downloading kernel source
+1. check your current kernel version
+ ```
+ uname -r
+ ```
+
+2. Find and download the real-time patch with matching major and minor versions from [here](https://cdn.kernel.org/pub/linux/kernel/projects/rt/) (*patch-\-rt\.patch.gz*)
+
+3. Download the kernel with identical version from [here](https://mirrors.edge.kernel.org/pub/linux/kernel/) (*linux-\.tar.gz*)
+
+4. Create directory to build kernel
+ ```
+ mkdir ~/kernel
+ cd ~/kernel
+ ```
+ - copy the downloaded archives to the `~/kernel` directory
+
+5. Unpack archives
+ ```
+ tar -xzf linux-.tar.gz
+ gunzip patch--rt.patch.gz
+ ```
+
+6. Patch the kernel with the realtime patch:
+ ```
+ cd linux-
+ patch -p1 < ../patch--rt.patch
+ ```
+
+7. Install dependencies needed for building the kernel
+ ```
+ sudo apt install libncurses-dev flex bison openssl libssl-dev dkms libelf-dev libudev-dev libpci-dev libiberty-dev autoconf fakeroot
+ ```
+
+### Kernel configuration
+
+#### Create configuration for building the kernel
+ - The easiest is to use the configuration of the current installation:
+ ```
+ cp /boot/config--generic .config
+ ```
+ - Modify certificates for signature checking
+ ```
+ scripts/config --disable SYSTEM_REVOCATION_KEYS
+ scripts/config --disable SYSTEM_REVOCATION_LIST
+ scripts/config --set-str SYSTEM_TRUSTED_KEYS ""
+ ```
+ - Enable all new Ubuntu configurations:
+ ```
+ yes '' | make oldconfig
+ ```
+
+#### Real-time adaptations
+ The kernel configuration must be modified to make it real-time-capable. Open GUI for modifications:
+ ```
+ make menuconfig
+ ```
+
+##### Enable fully preemptible kernel
+ ```
+ -> General Setup
+ -> Preemption Model
+ (X) Fully Preemptible Kernel (Real-Time)
+ ```
+
+##### Enable high resolution timer support
+ ```
+ -> General setup
+ -> Timers subsystem
+ [*] High Resolution Timer Support
+ ```
+
+##### Omit scheduling-clock ticks on isolated CPU-s
+ ```
+ -> General setup
+ -> Timers subsystem
+ -> Timer tick handling
+ (X) Full dynticks system (tickless)
+ ```
+
+##### Enforce maximum CPU frequency
+ ```
+ -> Power management and ACPI options
+ -> CPU Frequency scaling
+ -> CPU Frequency scaling
+ -> Default CPUFreq governor
+ (X) performance
+ ```
+
+Save (without modifying the name) and exit menuconfig.
+
+### Build and install kernel
+
+1. Build the kernel (which will take quite some time):
+ ```
+ make -j `getconf _NPROCESSORS_ONLN` deb-pkg
+ ```
+ After successful completion, there should be 4 debian packages in the `~/kernel` directory
+
+2. Install all kernel debian packages:
+ ```
+ sudo dpkg -i ../*.deb
+ ```
+
+3. Reboot
+ - Now the real time kernel should be installed. Reboot the system.
+ - At startup, choose the built kernel from the boot menu (*Advanced options*), or configure it to be default before restart.
+ - Check new kernel version with `uname -a`
+ - you should see `PREEMPT_RT` in the kernel version
+
+## Configuration
+
+After installing the real-time kernel, the setting of scheduling priorities must be enabled for your user:
+- extend `/etc/security/limits.conf` with
+```
+username - rtprio 98
+```
+- Restart the system
diff --git a/doc/wiki/Sunrise_FRI.md b/doc/wiki/Sunrise_FRI.md
new file mode 100644
index 00000000..1a6e9fad
--- /dev/null
+++ b/doc/wiki/Sunrise_FRI.md
@@ -0,0 +1,77 @@
+## Sunrise driver (FRI)
+
+### Setup
+
+#### Client side
+- It is recommended to use the driver on a real-time capable client machine (further information about setting up the PREEMPT_RT patch can be found [here](https://github.com/kroshu/kuka_drivers/wiki/Realtime)).
+- Set a fixed IP in the subnet of the controller for the real-time machine.
+
+#### Controller side
+
+- Upload the robot application under `robot_application/src` to the controller using the Sunrise Workbench
+
+### Configuration
+
+#### Startup configuration
+
+The following configuration files are available in the `config` directory of the package:
+- `driver_config.yaml`: contains IP addresses and runtime parameters
+- `ros2_controller_config.yaml`: contains the controller types for every controller name. Should be only modified if a different controller is to be used. The `configure_components_on_start` parameter should never be modified, which ensures that the hardware interface is not activated at startup.
+- configuration files for specific controllers, for further information, see the documentation of the given controller
+- `gpio_config.xacro`: contains the I/O setup of the system, but this was not tested yet
+
+##### IP configuration
+The following parameter must be set in the driver configuration file:
+- `controller_ip`: IP address of the controller
+
+#### Runtime parameters
+The parameters in the driver configuration file can be also changed during runtime using the parameter interface of the `robot_manager` node:
+- `send_period_ms` (integer): this parameter defines the send rate in milliseconds (with which the controller sends robot state updates). It must be between 1 and 10 for control and can be only changed in `inactive` and `configuring` states.
+- `receive_multiplier` (integer): this parameter defines the answer rate factor (the client should sends commands in every `receive_multiplier`*`send_period_ms` milliseconds). It must be at least 1 and can be only changed in `inactive` and `configuring` states.
+- `control_mode`, `command_mode` (strings): control mode related parameters, which will be combined to support the defined enums. They cannot be changed in active state.
+- `joint_damping`, `joint_stiffness` (double vectors): these parameters change the stiffness and damping attributes of joint impedance control mode. They will be removed after changing to using the `joint_group_impedance_controller` to adapt to conventions.
+
+### Usage
+
+#### Starting the driver
+
+1. On the controller, start the uploaded robot application (ROS2_Control).
+2. To start the driver, two launch file are available, with and without `rviz`. To launch (without `rviz`), run
+ ```
+ ros2 launch kuka_iiqka_eac_driver startup.launch.py`
+ ```
+ - This starts the 3 core components of every driver (described in the *Non-real-time interface* section of the [project overview](Project%20overview.md)) and the following controllers:
+ - `joint_state_broadcaster` (no configuration file, all state interfaces are published)
+ - `joint_trajectory_controller` ([configuration file](../../kuka_iiqka_eac_driver/config/joint_trajectory_controller_config.yaml))
+ - [`fri_configuration_controller`](https://github.com/kroshu/kuka_controllers?tab=readme-ov-file#fri_configuration_controller) (no configuration file)
+ - [`fri_state_broadcaster`](https://github.com/kroshu/kuka_controllers?tab=readme-ov-file#fri_state_broadcaster) (no configuration file)
+
+3. After successful startup, the `robot_manager` node has to be activated to start the cyclic communication with the robot controller (before this only a collapsed robot is visible in `rviz`):
+ ```
+ ros2 lifecycle set robot_manager configure
+ ros2 lifecycle set robot_manager activate
+ ```
+On successful activation the brakes of the robot will be released and external control is started using the requested control mode. To test moving the robot, the `rqt_joint_trajectory_controller` is not recommended, use the launch file in the `iiqka_moveit_example` package instead (usage is described in the *Additional packages* section of the [project overview](Project%20overview.md)).
+
+
+##### Launch arguments
+
+Both launch files support the following argument:
+- `robot_model`: defines which LBR iiwa robot to use. Available options: `lbr_iiwa14_r820` (default)
+- `use_fake_hardware`: if true, the `mock_components/GenericSystem` will be used instead of the `KukaRSIHardwareInterface`. This enables trying out the driver without actual hardware.
+
+#### Stopping external control
+
+To stop external control, all components have to be deactivated with `ros2 lifecycle set robot_manager deactivate`
+
+BEWARE, that this is a non-realtime process including lifecycle management, so the connection is not terminated immediately, in cases where an abrupt stop is needed, the safety stop of the Teach Pendant should be used! (This will also deactivate all components to allow reactivation without a restart.)
+
+
+### Known issues and limitations
+
+- Not all hardware-related communication is implemented in the hardware interface, therefore the mock hardware option is not working properly
+- The control mode handling for the driver is not the one defined in the `kuka_drivers_core` package
+ - enum definition and controller switching logic is not used
+ - joint impedance control is not implemented properly using command interfaces
+- I/O control was not tested at all
+- Cartesian modes are not yet supported
diff --git a/doc/wiki/iiQKA_EAC.md b/doc/wiki/iiQKA_EAC.md
new file mode 100644
index 00000000..23f14932
--- /dev/null
+++ b/doc/wiki/iiQKA_EAC.md
@@ -0,0 +1,80 @@
+## iiQKA driver (EAC)
+
+### Setup
+
+#### Client side
+- It is recommended to use the driver on a real-time capable client machine (further information about setting up the PREEMPT_RT patch can be found [here](https://github.com/kroshu/kuka_drivers/wiki/Realtime)).
+- The driver depends on some KUKA-specific packages, which are only available with the real robot, therefore a mock mode is provided to enable trying out solutions with the same components running.
+ - By default, the mock libraries are used, this can be changed in the `CmakeLists.txt` file by setting `MOCK_KUKA_LIBS` to `FALSE` before building.
+- Set a fixed IP in the subnet of the KONI interface for the real-time machine.
+
+#### Controller side
+
+- Install ExternalAPI.Control toolbox (requires iiQKA 1.2)
+- Set KONI IP (System Settings -> Network -> KONI) + restart
+- Connect external client to KONI port (XF7)
+- Release SPOC on the Teach Pendant
+
+### Configuration
+
+#### Startup configuration
+
+The following configuration files are available in the `config` directory of the package:
+- `driver_config.yaml`: contains IP addresses and runtime parameters
+- `qos_profiles.yaml`: contains the configuration options for the QoS profile defining the connection quality (description later)
+- `ros2_controller_config.yaml`: contains the controller types for every controller name. Should be only modified if a different controller is to be used. The `configure_components_on_start` parameter should never be modified, which ensures that the hardware interface is not activated at startup.
+- configuration files for specific controllers, for further information, see the documentation of the given controller
+
+##### QoS profile configuration
+It is possible to configure the required connection quality of external control using a QoS profile, which defines under which conditions should external control be terminated in case of packet losses. A packet is considered lost if the controller does not receive a command in 2.5 milliseconds after publishing the state. In case of a packet loss, extrapolation is used to optimize the robot behaviour, unless the limits defined in the profile are violated. Two limits can be defined:
+- Consequent packet losses allowed, defined by `consequent_lost_packets` parameter, maximum value is 5
+- Allowed packet losses in given timeframe: defined by `lost_packets_in_timeframe` (maximum value is 25) and `timeframe_ms` parameters, maximum ratio is 25/sec
+
+##### IP configuration
+The following parameters must be set in the driver configuration file:
+- `client_ip`: IP address of the client machine
+- `controller_ip`: KONI IP of the controller
+
+#### Runtime parameters
+The not IP-related parameters in the driver configuration file can be also changed during runtime using the parameter interface of the `robot_manager` node:
+- `control_mode`: The enum value of the control mode should be given. It can be changed in all primary states, but in active state the brakes are always closed before control is started in a new mode.
+- `position_controller_name`: The name of the controller (string) that controls the `position` interface of the robot. It can't be changed in active state.
+- `impedance_controller_name`: The name of the controller (string) that controls the `stiffness` and `damping` interfaces of the robot. It can't be changed in active state.
+- `torque_controller_name`: The name of the controller (string) that controls the `effort` interface of the robot. It can't be changed in active state.
+
+### Usage
+
+#### Starting the driver
+
+To start the driver, two launch file are available, with and without `rviz`. To launch (without `rviz`), run:
+
+```
+ros2 launch kuka_iiqka_eac_driver startup.launch.py
+```
+
+This starts the 3 core components of every driver (described in the *Non-real-time interface* section of the [project overview](Project%20overview.md)) and the following controllers:
+- `joint_state_broadcaster` (no configuration file, all state interfaces are published)
+- `joint_trajectory_controller` ([configuration file](../../kuka_iiqka_eac_driver/config/joint_trajectory_controller_config.yaml))
+- `joint_group_impedance_controller` ([configuration file](../../kuka_iiqka_eac_driver/config/joint_impedance_controller_config.yaml))
+- `effort_controller` (of type `JointGroupPositionController`, [configuration file](../../kuka_iiqka_eac_driver/config/effort_controller_config.yaml))
+- [`control_mode_handler`](https://github.com/kroshu/kuka_controllers?tab=readme-ov-file#control_mode_handler) (no configuration file)
+
+After successful startup, the `robot_manager` node has to be activated to start the cyclic communication with the robot controller (before this only a collapsed robot is visible in `rviz`):
+ ```
+ ros2 lifecycle set robot_manager configure
+ ros2 lifecycle set robot_manager activate
+ ```
+
+On successful activation the brakes of the robot will be released and external control is started using the requested control mode. To test moving the robot, the `rqt_joint_trajectory_controller` is not recommended, use the launch file in the `iiqka_moveit_example` package instead (usage is described in the *Additional packages* section of the [project overview](Project%20overview.md)).
+
+
+##### Launch arguments
+
+Both launch files support the following argument:
+- `robot_model`: defines which LBR iisy robot to use. Available options: `lbr_iisy3_r760` (default), `lbr_iisy11_r1300`, `lbr_iisy15_r930`
+
+#### Stopping external control
+
+To stop external control, all components have to be deactivated with `ros2 lifecycle set robot_manager deactivate`
+
+BEWARE, that this is a non-realtime process including lifecycle management, so the connection is not terminated immediately, in cases where an abrupt stop is needed, the safety stop of the Teach Pendant should be used! (This will also deactivate all components to allow reactivation without a restart.)
diff --git a/examples/iiqka_moveit_example/CMakeLists.txt b/examples/iiqka_moveit_example/CMakeLists.txt
index db9ac4e5..c9e82446 100755
--- a/examples/iiqka_moveit_example/CMakeLists.txt
+++ b/examples/iiqka_moveit_example/CMakeLists.txt
@@ -74,23 +74,7 @@ install(DIRECTORY config
)
if(BUILD_TESTING)
- find_package(ament_cmake_copyright REQUIRED)
- find_package(ament_cmake_cppcheck REQUIRED)
- find_package(ament_cmake_pep257 REQUIRED)
- find_package(ament_cmake_flake8 REQUIRED)
- find_package(ament_cmake_cpplint REQUIRED)
- find_package(ament_cmake_lint_cmake REQUIRED)
- find_package(ament_cmake_uncrustify REQUIRED)
- find_package(ament_cmake_xmllint REQUIRED)
- ament_copyright()
- ament_cppcheck(--language=c++)
- ament_pep257()
- ament_flake8()
- ament_cpplint()
- ament_lint_cmake()
- ament_uncrustify()
- ament_xmllint()
endif()
ament_package()
diff --git a/examples/iiqka_moveit_example/CONTRIBUTING.md b/examples/iiqka_moveit_example/CONTRIBUTING.md
index acae8da3..6f63de9e 100644
--- a/examples/iiqka_moveit_example/CONTRIBUTING.md
+++ b/examples/iiqka_moveit_example/CONTRIBUTING.md
@@ -11,4 +11,3 @@ be under the Apache 2 License, as dictated by that
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
~~~
-
diff --git a/examples/iiqka_moveit_example/config/dummy_impedance_publisher.yaml b/examples/iiqka_moveit_example/config/dummy_impedance_publisher.yaml
deleted file mode 100644
index f5ebfe95..00000000
--- a/examples/iiqka_moveit_example/config/dummy_impedance_publisher.yaml
+++ /dev/null
@@ -1,15 +0,0 @@
-/publisher_joint_impedance_controller:
- ros__parameters:
-
- controller_name: "joint_group_impedance_controller"
-
- stiffness_goals: [30, 0, 30, 30, 30, 30]
- damping_goals: [0.7, 0.0, 0.7, 0.7, 0.7, 0.7]
-
- joints:
- - joint_1
- - joint_2
- - joint_3
- - joint_4
- - joint_5
- - joint_6
diff --git a/examples/iiqka_moveit_example/config/dummy_publisher.yaml b/examples/iiqka_moveit_example/config/dummy_publisher.yaml
index 6b2a013f..08f5cb57 100644
--- a/examples/iiqka_moveit_example/config/dummy_publisher.yaml
+++ b/examples/iiqka_moveit_example/config/dummy_publisher.yaml
@@ -5,13 +5,13 @@
wait_sec_between_publish: 6
goal_names: ["pos1", "pos2", "pos3", "pos4"]
- pos1:
+ pos1:
positions: [0.0, -1.57, 0.0, 0.0, 0.0, 0.0]
- pos2:
+ pos2:
positions: [0.0, -1.37, 0.0, 0.0, 0.0, 0.0]
- pos3:
+ pos3:
positions: [0.2, -1.57, 0.2, 0.2, 0.2, 0.2]
- pos4:
+ pos4:
positions: [-0.2, -1.57, -0.2, -0.2, -0.2, -0.2]
joints:
diff --git a/examples/iiqka_moveit_example/config/moveit_controllers.yaml b/examples/iiqka_moveit_example/config/moveit_controllers.yaml
index 3dd73c3f..486bcb5c 100644
--- a/examples/iiqka_moveit_example/config/moveit_controllers.yaml
+++ b/examples/iiqka_moveit_example/config/moveit_controllers.yaml
@@ -21,4 +21,3 @@ moveit_simple_controller_manager:
- joint_4
- joint_5
- joint_6
-
diff --git a/examples/iiqka_moveit_example/include/iiqka_moveit_example/moveit_example.hpp b/examples/iiqka_moveit_example/include/iiqka_moveit_example/moveit_example.hpp
old mode 100755
new mode 100644
index 3634425d..ade40bea
--- a/examples/iiqka_moveit_example/include/iiqka_moveit_example/moveit_example.hpp
+++ b/examples/iiqka_moveit_example/include/iiqka_moveit_example/moveit_example.hpp
@@ -21,26 +21,22 @@
#include
#include
-#include "rclcpp/rclcpp.hpp"
+#include "geometry_msgs/msg/vector3.hpp"
#include "moveit/move_group_interface/move_group_interface.h"
#include "moveit/planning_scene_interface/planning_scene_interface.h"
#include "moveit_msgs/msg/collision_object.hpp"
#include "moveit_visual_tools/moveit_visual_tools.h"
-#include "geometry_msgs/msg/vector3.hpp"
+#include "rclcpp/rclcpp.hpp"
class MoveitExample : public rclcpp::Node
{
public:
- MoveitExample()
- : rclcpp::Node("moveit_example")
- {
- }
+ MoveitExample() : rclcpp::Node("moveit_example") {}
void initialize()
{
move_group_interface_ = std::make_shared(
- shared_from_this(),
- PLANNING_GROUP);
+ shared_from_this(), PLANNING_GROUP);
moveit_visual_tools_ = std::make_shared(
shared_from_this(), "base_link", rviz_visual_tools::RVIZ_MARKER_TOPIC,
@@ -50,8 +46,8 @@ class MoveitExample : public rclcpp::Node
moveit_visual_tools_->loadRemoteControl();
moveit_visual_tools_->trigger();
- planning_scene_diff_publisher_ = this->create_publisher(
- "planning_scene", 10);
+ planning_scene_diff_publisher_ =
+ this->create_publisher("planning_scene", 10);
move_group_interface_->setMaxVelocityScalingFactor(0.1);
move_group_interface_->setMaxAccelerationScalingFactor(0.1);
@@ -70,7 +66,8 @@ class MoveitExample : public rclcpp::Node
msg.orientation.w = sqrt(2) / 2;
msg.position.x = 0.4;
// Define waypoints in a circle
- for (int i = 0; i < 63; i++) {
+ for (int i = 0; i < 63; i++)
+ {
msg.position.y = -0.2 + sin(0.1 * i) * 0.15;
msg.position.z = 0.4 + cos(0.1 * i) * 0.15;
waypoints.push_back(msg);
@@ -81,10 +78,13 @@ class MoveitExample : public rclcpp::Node
move_group_interface_->computeCartesianPath(waypoints, 0.005, 0.0, trajectory);
RCLCPP_INFO(LOGGER, "Planning done!");
- if (fraction < 1) {
+ if (fraction < 1)
+ {
RCLCPP_ERROR(LOGGER, "Could not compute trajectory through all waypoints!");
return nullptr;
- } else {
+ }
+ else
+ {
return std::make_shared(trajectory);
}
}
@@ -101,26 +101,31 @@ class MoveitExample : public rclcpp::Node
moveit::planning_interface::MoveGroupInterface::Plan plan;
RCLCPP_INFO(LOGGER, "Sending planning request");
- if (!move_group_interface_->plan(plan)) {
+ if (!move_group_interface_->plan(plan))
+ {
RCLCPP_INFO(LOGGER, "Planning failed");
return nullptr;
- } else {
+ }
+ else
+ {
RCLCPP_INFO(LOGGER, "Planning successful");
return std::make_shared(plan.trajectory_);
}
}
- moveit_msgs::msg::RobotTrajectory::SharedPtr planToPosition(
- const std::vector & joint_pos)
+ moveit_msgs::msg::RobotTrajectory::SharedPtr planToPosition(const std::vector & joint_pos)
{
move_group_interface_->setJointValueTarget(joint_pos);
moveit::planning_interface::MoveGroupInterface::Plan plan;
RCLCPP_INFO(LOGGER, "Sending planning request");
- if (!move_group_interface_->plan(plan)) {
+ if (!move_group_interface_->plan(plan))
+ {
RCLCPP_INFO(LOGGER, "Planning failed");
return nullptr;
- } else {
+ }
+ else
+ {
RCLCPP_INFO(LOGGER, "Planning successful");
return std::make_shared(plan.trajectory_);
}
@@ -140,7 +145,8 @@ class MoveitExample : public rclcpp::Node
RCLCPP_INFO(LOGGER, "Sending planning request");
moveit::core::MoveItErrorCode err_code;
auto start = std::chrono::high_resolution_clock::now();
- do{
+ do
+ {
RCLCPP_INFO(LOGGER, "Planning ...");
err_code = move_group_interface_->plan(plan);
} while (err_code != moveit::core::MoveItErrorCode::SUCCESS);
@@ -186,8 +192,7 @@ class MoveitExample : public rclcpp::Node
}
void addCollisionBox(
- const geometry_msgs::msg::Vector3 & position,
- const geometry_msgs::msg::Vector3 & size)
+ const geometry_msgs::msg::Vector3 & position, const geometry_msgs::msg::Vector3 & size)
{
moveit_msgs::msg::CollisionObject collision_object;
collision_object.header.frame_id = move_group_interface_->getPlanningFrame();
@@ -215,9 +220,12 @@ class MoveitExample : public rclcpp::Node
void addPalletObjects()
{
- for (int k = 0; k < 3; k++) {
- for (int j = 0; j < 3; j++) {
- for (int i = 0; i < 3; i++) {
+ for (int k = 0; k < 3; k++)
+ {
+ for (int j = 0; j < 3; j++)
+ {
+ for (int i = 0; i < 3; i++)
+ {
moveit_msgs::msg::CollisionObject pallet_object;
pallet_object.header.frame_id = move_group_interface_->getPlanningFrame();
@@ -299,30 +307,25 @@ class MoveitExample : public rclcpp::Node
move_group_interface_->setPathConstraints(constraints);
}
- void clearConstraints()
- {
- move_group_interface_->clearPathConstraints();
- }
+ void clearConstraints() { move_group_interface_->clearPathConstraints(); }
void drawTrajectory(const moveit_msgs::msg::RobotTrajectory & trajectory)
{
moveit_visual_tools_->deleteAllMarkers();
moveit_visual_tools_->publishTrajectoryLine(
- trajectory,
- moveit_visual_tools_->getRobotModel()->getJointModelGroup(PLANNING_GROUP));
+ trajectory, moveit_visual_tools_->getRobotModel()->getJointModelGroup(PLANNING_GROUP));
}
void drawTitle(const std::string & text)
{
auto const text_pose = []
- {
- auto msg = Eigen::Isometry3d::Identity();
- msg.translation().z() = 1.0;
- return msg;
- } ();
+ {
+ auto msg = Eigen::Isometry3d::Identity();
+ msg.translation().z() = 1.0;
+ return msg;
+ }();
moveit_visual_tools_->publishText(
- text_pose, text, rviz_visual_tools::RED,
- rviz_visual_tools::XXLARGE);
+ text_pose, text, rviz_visual_tools::RED, rviz_visual_tools::XXLARGE);
}
void addBreakPoint()
diff --git a/examples/iiqka_moveit_example/launch/launch_impedance_publisher.launch.py b/examples/iiqka_moveit_example/launch/launch_impedance_publisher.launch.py
deleted file mode 100644
index c57b108c..00000000
--- a/examples/iiqka_moveit_example/launch/launch_impedance_publisher.launch.py
+++ /dev/null
@@ -1,42 +0,0 @@
-# Copyright 2022 Márk Szitanics
-#
-# 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.
-
-
-from launch import LaunchDescription
-from launch.substitutions import PathJoinSubstitution
-from launch_ros.actions import Node
-from launch_ros.substitutions import FindPackageShare
-
-
-def generate_launch_description():
-
- impedance_config = PathJoinSubstitution(
- [
- FindPackageShare("iiqka_moveit_example"),
- "config",
- "dummy_impedance_publisher.yaml",
- ]
- )
- # TODO: create a dummy publisher script in the ros2_control_test_nodes repo
- return LaunchDescription(
- [
- Node(
- package="ros2_controllers_test_nodes",
- executable="publisher_joint_impedance_controller",
- name="publisher_joint_impedance_controller",
- parameters=[impedance_config],
- output="both",
- )
- ]
- )
diff --git a/examples/iiqka_moveit_example/launch/launch_trajectory_publisher.launch.py b/examples/iiqka_moveit_example/launch/launch_trajectory_publisher.launch.py
index bfa97259..e7d91d7c 100644
--- a/examples/iiqka_moveit_example/launch/launch_trajectory_publisher.launch.py
+++ b/examples/iiqka_moveit_example/launch/launch_trajectory_publisher.launch.py
@@ -19,7 +19,6 @@
def generate_launch_description():
-
position_goals = PathJoinSubstitution(
[
FindPackageShare("iiqka_moveit_example"),
diff --git a/examples/iiqka_moveit_example/launch/moveit_planning_example.launch.py b/examples/iiqka_moveit_example/launch/moveit_planning_example.launch.py
index a8d3c660..b4338688 100644
--- a/examples/iiqka_moveit_example/launch/moveit_planning_example.launch.py
+++ b/examples/iiqka_moveit_example/launch/moveit_planning_example.launch.py
@@ -18,40 +18,52 @@
from moveit_configs_utils import MoveItConfigsBuilder
from launch.actions.include_launch_description import IncludeLaunchDescription
from launch.actions import DeclareLaunchArgument, OpaqueFunction
-from launch.launch_description_sources.python_launch_description_source import PythonLaunchDescriptionSource # noqa: E501
+from launch.launch_description_sources.python_launch_description_source import (
+ PythonLaunchDescriptionSource,
+) # noqa: E501
from launch.substitutions import LaunchConfiguration
def launch_setup(context, *args, **kwargs):
- robot_model = LaunchConfiguration('robot_model')
+ robot_model = LaunchConfiguration("robot_model")
moveit_config = (
MoveItConfigsBuilder("kuka_lbr_iisy")
- .robot_description(file_path=get_package_share_directory('kuka_lbr_iisy_support')
- + "/urdf/{}.urdf.xacro".format(robot_model.perform(context)))
- .robot_description_semantic(get_package_share_directory('kuka_lbr_iisy_moveit_config') # noqa: E501
- + "/urdf/{}.srdf".format(robot_model.perform(context)))
+ .robot_description(
+ file_path=get_package_share_directory("kuka_lbr_iisy_support")
+ + f"/urdf/{robot_model.perform(context)}.urdf.xacro"
+ )
+ .robot_description_semantic(
+ get_package_share_directory("kuka_lbr_iisy_moveit_config") # noqa: E501
+ + f"/urdf/{robot_model.perform(context)}.srdf"
+ )
.robot_description_kinematics(file_path="config/kinematics.yaml")
.trajectory_execution(file_path="config/moveit_controllers.yaml")
.planning_scene_monitor(
publish_robot_description=True, publish_robot_description_semantic=True
)
- .joint_limits(file_path=get_package_share_directory('kuka_lbr_iisy_support')
- + "/config/{}_joint_limits.yaml".format(robot_model.perform(context)))
+ .joint_limits(
+ file_path=get_package_share_directory("kuka_lbr_iisy_support")
+ + f"/config/{robot_model.perform(context)}_joint_limits.yaml"
+ )
.to_moveit_configs()
)
- rviz_config_file = get_package_share_directory(
- 'kuka_resources') + "/config/view_6_axis_urdf.rviz"
+ rviz_config_file = (
+ get_package_share_directory("kuka_resources") + "/config/view_6_axis_planning_scene.rviz"
+ )
- startup_launch = IncludeLaunchDescription(PythonLaunchDescriptionSource(
- [get_package_share_directory('kuka_iiqka_eac_driver'), '/launch/startup.launch.py']),
- launch_arguments={'robot_model': "{}".format(robot_model.perform(context))}.items())
+ startup_launch = IncludeLaunchDescription(
+ PythonLaunchDescriptionSource(
+ [get_package_share_directory("kuka_iiqka_eac_driver"), "/launch/startup.launch.py"]
+ ),
+ launch_arguments={"robot_model": f"{robot_model.perform(context)}"}.items(),
+ )
move_group_server = Node(
package="moveit_ros_move_group",
executable="move_group",
output="screen",
- parameters=[moveit_config.to_dict(), {'publish_planning_scene_hz': 30.0}],
+ parameters=[moveit_config.to_dict(), {"publish_planning_scene_hz": 30.0}],
)
rviz = Node(
@@ -62,19 +74,12 @@ def launch_setup(context, *args, **kwargs):
arguments=["-d", rviz_config_file, "--ros-args", "--log-level", "error"],
)
- to_start = [
- startup_launch,
- move_group_server,
- rviz
- ]
+ to_start = [startup_launch, move_group_server, rviz]
return to_start
def generate_launch_description():
launch_arguments = []
- launch_arguments.append(DeclareLaunchArgument(
- 'robot_model',
- default_value='lbr_iisy3_r760'
- ))
+ launch_arguments.append(DeclareLaunchArgument("robot_model", default_value="lbr_iisy3_r760"))
return LaunchDescription(launch_arguments + [OpaqueFunction(function=launch_setup)])
diff --git a/examples/iiqka_moveit_example/package.xml b/examples/iiqka_moveit_example/package.xml
index 401a5d38..4e2fe719 100644
--- a/examples/iiqka_moveit_example/package.xml
+++ b/examples/iiqka_moveit_example/package.xml
@@ -3,9 +3,9 @@
iiqka_moveit_example
0.0.0
- ROS package using the RoX driver
+ ROS example package using the iiQKA driver and moveit
Aron Svastits
- BSD
+ Apache 2.0
ament_cmake
moveit_common
@@ -19,16 +19,7 @@
ros2_controllers
moveit
-
- ament_lint_auto
- ament_lint_common
- ament_cmake_copyright
- ament_cmake_cppcheck
- ament_cmake_pep257
- ament_cmake_flake8
- ament_cmake_cpplint
- ament_cmake_lint_cmake
- ament_cmake_xmllint
+ ros2_controllers_test_nodes
ament_cmake
diff --git a/examples/iiqka_moveit_example/src/moveit_basic_planners_example.cpp b/examples/iiqka_moveit_example/src/moveit_basic_planners_example.cpp
old mode 100755
new mode 100644
index 975a9deb..d840a6e8
--- a/examples/iiqka_moveit_example/src/moveit_basic_planners_example.cpp
+++ b/examples/iiqka_moveit_example/src/moveit_basic_planners_example.cpp
@@ -18,7 +18,6 @@
#include "iiqka_moveit_example/moveit_example.hpp"
-
int main(int argc, char * argv[])
{
// Setup
@@ -27,10 +26,7 @@ int main(int argc, char * argv[])
auto const example_node = std::make_shared();
rclcpp::executors::SingleThreadedExecutor executor;
executor.add_node(example_node);
- std::thread(
- [&executor]()
- {executor.spin();})
- .detach();
+ std::thread([&executor]() { executor.spin(); }).detach();
example_node->initialize();
example_node->addBreakPoint();
@@ -39,16 +35,13 @@ int main(int argc, char * argv[])
example_node->addRobotPlatform();
// Pilz PTP planner
- auto standing_pose = Eigen::Isometry3d(
- Eigen::Translation3d(
- 0.1, 0,
- 0.8) *
- Eigen::Quaterniond::Identity());
+ auto standing_pose =
+ Eigen::Isometry3d(Eigen::Translation3d(0.1, 0, 0.8) * Eigen::Quaterniond::Identity());
- auto planned_trajectory = example_node->planToPoint(
- standing_pose,
- "pilz_industrial_motion_planner", "PTP");
- if (planned_trajectory != nullptr) {
+ auto planned_trajectory =
+ example_node->planToPoint(standing_pose, "pilz_industrial_motion_planner", "PTP");
+ if (planned_trajectory != nullptr)
+ {
example_node->drawTrajectory(*planned_trajectory);
example_node->addBreakPoint();
example_node->moveGroupInterface()->execute(*planned_trajectory);
@@ -56,14 +49,12 @@ int main(int argc, char * argv[])
example_node->addBreakPoint();
// Pilz LIN planner
- auto cart_goal = Eigen::Isometry3d(
- Eigen::Translation3d(
- 0.4, -0.15,
- 0.55) *
- Eigen::Quaterniond::Identity());
+ auto cart_goal =
+ Eigen::Isometry3d(Eigen::Translation3d(0.4, -0.15, 0.55) * Eigen::Quaterniond::Identity());
planned_trajectory =
example_node->planToPoint(cart_goal, "pilz_industrial_motion_planner", "LIN");
- if (planned_trajectory != nullptr) {
+ if (planned_trajectory != nullptr)
+ {
example_node->drawTrajectory(*planned_trajectory);
example_node->addBreakPoint();
example_node->moveGroupInterface()->execute(*planned_trajectory);
@@ -76,23 +67,27 @@ int main(int argc, char * argv[])
example_node->addBreakPoint();
// Try moving back with Pilz LIN
- planned_trajectory = example_node->planToPoint(
- standing_pose, "pilz_industrial_motion_planner",
- "LIN");
- if (planned_trajectory != nullptr) {
+ planned_trajectory =
+ example_node->planToPoint(standing_pose, "pilz_industrial_motion_planner", "LIN");
+ if (planned_trajectory != nullptr)
+ {
example_node->drawTrajectory(*planned_trajectory);
- } else {
+ }
+ else
+ {
example_node->drawTitle("Failed planning with Pilz LIN");
}
example_node->addBreakPoint();
// Try moving back with Pilz PTP
- planned_trajectory = example_node->planToPoint(
- standing_pose, "pilz_industrial_motion_planner",
- "PTP");
- if (planned_trajectory != nullptr) {
+ planned_trajectory =
+ example_node->planToPoint(standing_pose, "pilz_industrial_motion_planner", "PTP");
+ if (planned_trajectory != nullptr)
+ {
example_node->drawTrajectory(*planned_trajectory);
- } else {
+ }
+ else
+ {
example_node->drawTitle("Failed planning with Pilz PTP");
}
example_node->addBreakPoint();
diff --git a/examples/iiqka_moveit_example/src/moveit_collision_avoidance_example.cpp b/examples/iiqka_moveit_example/src/moveit_collision_avoidance_example.cpp
old mode 100755
new mode 100644
index 006d514b..77021749
--- a/examples/iiqka_moveit_example/src/moveit_collision_avoidance_example.cpp
+++ b/examples/iiqka_moveit_example/src/moveit_collision_avoidance_example.cpp
@@ -25,10 +25,7 @@ int main(int argc, char * argv[])
auto const example_node = std::make_shared();
rclcpp::executors::SingleThreadedExecutor executor;
executor.add_node(example_node);
- std::thread(
- [&executor]()
- {executor.spin();})
- .detach();
+ std::thread([&executor]() { executor.spin(); }).detach();
example_node->initialize();
@@ -38,7 +35,8 @@ int main(int argc, char * argv[])
// Go to correct position for the example
auto init_trajectory = example_node->planToPosition(
std::vector{0.3587, 0.3055, -1.3867, 0.0, -0.4896, -0.3587});
- if (init_trajectory != nullptr) {
+ if (init_trajectory != nullptr)
+ {
example_node->moveGroupInterface()->execute(*init_trajectory);
}
@@ -48,17 +46,14 @@ int main(int argc, char * argv[])
geometry_msgs::build().x(0.1).y(1.0).z(0.1));
example_node->addBreakPoint();
- auto standing_pose = Eigen::Isometry3d(
- Eigen::Translation3d(
- 0.1, 0,
- 0.8) *
- Eigen::Quaterniond::Identity());
+ auto standing_pose =
+ Eigen::Isometry3d(Eigen::Translation3d(0.1, 0, 0.8) * Eigen::Quaterniond::Identity());
// Plan with collision avoidance
- auto planned_trajectory = example_node->planToPoint(
- standing_pose, "ompl",
- "RRTConnectkConfigDefault");
- if (planned_trajectory != nullptr) {
+ auto planned_trajectory =
+ example_node->planToPoint(standing_pose, "ompl", "RRTConnectkConfigDefault");
+ if (planned_trajectory != nullptr)
+ {
example_node->drawTrajectory(*planned_trajectory);
example_node->addBreakPoint();
example_node->moveGroupInterface()->execute(*planned_trajectory);
diff --git a/examples/iiqka_moveit_example/src/moveit_constrained_planning_example.cpp b/examples/iiqka_moveit_example/src/moveit_constrained_planning_example.cpp
old mode 100755
new mode 100644
index ff79429e..0053d233
--- a/examples/iiqka_moveit_example/src/moveit_constrained_planning_example.cpp
+++ b/examples/iiqka_moveit_example/src/moveit_constrained_planning_example.cpp
@@ -25,10 +25,7 @@ int main(int argc, char * argv[])
auto const example_node = std::make_shared();
rclcpp::executors::SingleThreadedExecutor executor;
executor.add_node(example_node);
- std::thread(
- [&executor]()
- {executor.spin();})
- .detach();
+ std::thread([&executor]() { executor.spin(); }).detach();
example_node->initialize();
@@ -38,7 +35,8 @@ int main(int argc, char * argv[])
// Go to correct position for the example
auto init_trajectory = example_node->planToPosition(
std::vector{0.0017, -2.096, 1.514, 0.0012, -0.9888, -0.0029});
- if (init_trajectory != nullptr) {
+ if (init_trajectory != nullptr)
+ {
example_node->moveGroupInterface()->execute(*init_trajectory);
}
@@ -48,11 +46,8 @@ int main(int argc, char * argv[])
geometry_msgs::build().x(0.1).y(1.0).z(0.1));
example_node->addBreakPoint();
- auto cart_goal = Eigen::Isometry3d(
- Eigen::Translation3d(
- 0.4, -0.15,
- 0.55) *
- Eigen::Quaterniond::Identity());
+ auto cart_goal =
+ Eigen::Isometry3d(Eigen::Translation3d(0.4, -0.15, 0.55) * Eigen::Quaterniond::Identity());
geometry_msgs::msg::Quaternion q;
q.x = 0;
@@ -66,7 +61,8 @@ int main(int argc, char * argv[])
// Plan with collision avoidance
auto planned_trajectory =
example_node->planToPointUntilSuccess(cart_goal, "ompl", "RRTkConfigDefault");
- if (planned_trajectory != nullptr) {
+ if (planned_trajectory != nullptr)
+ {
example_node->drawTrajectory(*planned_trajectory);
example_node->addBreakPoint();
example_node->moveGroupInterface()->execute(*planned_trajectory);
diff --git a/examples/iiqka_moveit_example/src/moveit_depalletizing_example.cpp b/examples/iiqka_moveit_example/src/moveit_depalletizing_example.cpp
old mode 100755
new mode 100644
index b4b1aa72..7b28611f
--- a/examples/iiqka_moveit_example/src/moveit_depalletizing_example.cpp
+++ b/examples/iiqka_moveit_example/src/moveit_depalletizing_example.cpp
@@ -23,23 +23,27 @@ class Depalletizer : public MoveitExample
public:
void Depalletize()
{
- for (int k = 0; k < 3; k++) {
- for (int j = 0; j < 3; j++) {
- for (int i = 0; i < 3; i++) {
+ for (int k = 0; k < 3; k++)
+ {
+ for (int j = 0; j < 3; j++)
+ {
+ for (int i = 0; i < 3; i++)
+ {
std::string object_name = "pallet_" + std::to_string(9 * k + 3 * j + i);
RCLCPP_INFO(LOGGER, "Going for object %s", object_name.c_str());
// Go to pickup
Eigen::Isometry3d pose = Eigen::Isometry3d(
- Eigen::Translation3d(
- 0.3 + i * 0.1, j * 0.1 - 0.1,
- 0.35 - 0.1 * k) *
+ Eigen::Translation3d(0.3 + i * 0.1, j * 0.1 - 0.1, 0.35 - 0.1 * k) *
Eigen::Quaterniond(0, 1, 0, 0));
auto planned_trajectory =
planToPointUntilSuccess(pose, "ompl", "RRTConnectkConfigDefault");
- if (planned_trajectory != nullptr) {
+ if (planned_trajectory != nullptr)
+ {
move_group_interface_->execute(*planned_trajectory);
- } else {
+ }
+ else
+ {
RCLCPP_ERROR(LOGGER, "Planning failed");
}
@@ -49,12 +53,14 @@ class Depalletizer : public MoveitExample
// Drop off to -0.3, 0.0, 0.35 pointing down
Eigen::Isometry3d dropoff_pose = Eigen::Isometry3d(
Eigen::Translation3d(-0.3, 0.0, 0.35) * Eigen::Quaterniond(0, 1, 0, 0));
- auto drop_trajectory = planToPointUntilSuccess(
- dropoff_pose, "ompl",
- "RRTConnectkConfigDefault");
- if (drop_trajectory != nullptr) {
+ auto drop_trajectory =
+ planToPointUntilSuccess(dropoff_pose, "ompl", "RRTConnectkConfigDefault");
+ if (drop_trajectory != nullptr)
+ {
move_group_interface_->execute(*drop_trajectory);
- } else {
+ }
+ else
+ {
RCLCPP_ERROR(LOGGER, "Planning failed");
}
@@ -74,10 +80,7 @@ int main(int argc, char * argv[])
auto const node = std::make_shared();
rclcpp::executors::SingleThreadedExecutor executor;
executor.add_node(node);
- std::thread(
- [&executor]()
- {executor.spin();})
- .detach();
+ std::thread([&executor]() { executor.spin(); }).detach();
node->initialize();
diff --git a/kuka_driver_interfaces/CMakeLists.txt b/kuka_driver_interfaces/CMakeLists.txt
index 9976f108..b921b7dc 100644
--- a/kuka_driver_interfaces/CMakeLists.txt
+++ b/kuka_driver_interfaces/CMakeLists.txt
@@ -31,8 +31,7 @@ rosidl_generate_interfaces(${PROJECT_NAME}
if(BUILD_TESTING)
- find_package(ament_lint_auto REQUIRED)
- ament_lint_auto_find_test_dependencies()
+
endif()
ament_package()
diff --git a/kuka_driver_interfaces/msg/FRIState.msg b/kuka_driver_interfaces/msg/FRIState.msg
index 8b18d3f9..5586374e 100644
--- a/kuka_driver_interfaces/msg/FRIState.msg
+++ b/kuka_driver_interfaces/msg/FRIState.msg
@@ -1,6 +1,6 @@
# Message describing the state of the robot and FRI
-# FRI session state enum
+# FRI session state enum
# IDLE = 0, MONITORING_WAIT = 1, MONITORING_READY = 2,COMMANDING_WAIT = 3, COMMANDING_ACTIVE = 4
int32 session_state
diff --git a/kuka_driver_interfaces/package.xml b/kuka_driver_interfaces/package.xml
index 42903baf..57e737f9 100644
--- a/kuka_driver_interfaces/package.xml
+++ b/kuka_driver_interfaces/package.xml
@@ -10,11 +10,8 @@
ament_cmake
rosidl_default_generators
- ament_lint_auto
- ament_lint_common
-
geometry_msgs
-
+
rosidl_default_runtime
rosidl_interface_packages
diff --git a/kuka_drivers/CMakeLists.txt b/kuka_drivers/CMakeLists.txt
index 4b8f9700..395bca9f 100644
--- a/kuka_drivers/CMakeLists.txt
+++ b/kuka_drivers/CMakeLists.txt
@@ -7,4 +7,4 @@ endif()
find_package(ament_cmake REQUIRED)
-ament_package()
\ No newline at end of file
+ament_package()
diff --git a/kuka_drivers/package.xml b/kuka_drivers/package.xml
index ec9af207..8436e6a0 100644
--- a/kuka_drivers/package.xml
+++ b/kuka_drivers/package.xml
@@ -2,10 +2,10 @@
kuka_drivers
0.0.1
- ROS2 Controllers for KUKA robots
+ ROS2 drivers for KUKA robots
Áron Svastits
Áron Svastits
- BSD
+ Apache 2.0
https://github.com/kroshu/kuka_drivers/issues
https://github.com/kroshu/kuka_drivers
diff --git a/kuka_drivers_core/CMakeLists.txt b/kuka_drivers_core/CMakeLists.txt
index 2a73eb83..48a21295 100644
--- a/kuka_drivers_core/CMakeLists.txt
+++ b/kuka_drivers_core/CMakeLists.txt
@@ -71,23 +71,7 @@ install(TARGETS ${PROJECT_NAME} control_node
ament_export_include_directories(include)
if(BUILD_TESTING)
- find_package(ament_cmake_copyright REQUIRED)
- find_package(ament_cmake_cppcheck REQUIRED)
- find_package(ament_cmake_pep257 REQUIRED)
- find_package(ament_cmake_flake8 REQUIRED)
- find_package(ament_cmake_cpplint REQUIRED)
- find_package(ament_cmake_lint_cmake REQUIRED)
- find_package(ament_cmake_uncrustify REQUIRED)
- find_package(ament_cmake_xmllint REQUIRED)
-
- ament_copyright()
- ament_cppcheck(--language=c++)
- ament_pep257()
- ament_flake8()
- ament_cpplint()
- ament_lint_cmake()
- ament_uncrustify()
- ament_xmllint()
+
endif()
ament_package()
diff --git a/kuka_drivers_core/README.md b/kuka_drivers_core/README.md
index 9cf8140d..efbdeb41 100644
--- a/kuka_drivers_core/README.md
+++ b/kuka_drivers_core/README.md
@@ -1,5 +1,5 @@
# Core classes which help function the repositories of kroshu.
-These classes provide functonalities which are frequently used in ROS2 environment.
+These classes provide functionalities which are frequently used in ROS2 environment.
Deriving from these classes the user has a helpful wrapper around the base functionalities of ROS2.
Right now there are two classes implemented in this repository, ROS2BaseNode for simple parameter handling, and ROS2BaseLCNode, which additionally furthers the rclcpp_lifecycle::LifecycleNode class by implementing lifecycle functions which would be usually implemented in the same way in every case. These are virtual functions, so it is possible to override them in the case of a different desired implementation.
diff --git a/kuka_drivers_core/include/communication_helpers/ros2_control_tools.hpp b/kuka_drivers_core/include/communication_helpers/ros2_control_tools.hpp
index 259d17cc..4054ada3 100644
--- a/kuka_drivers_core/include/communication_helpers/ros2_control_tools.hpp
+++ b/kuka_drivers_core/include/communication_helpers/ros2_control_tools.hpp
@@ -15,14 +15,14 @@
#ifndef COMMUNICATION_HELPERS__ROS2_CONTROL_TOOLS_HPP_
#define COMMUNICATION_HELPERS__ROS2_CONTROL_TOOLS_HPP_
+#include
#include
#include
-#include
-#include "rclcpp/rclcpp.hpp"
+#include "communication_helpers/service_tools.hpp"
#include "controller_manager_msgs/srv/set_hardware_component_state.hpp"
#include "controller_manager_msgs/srv/switch_controller.hpp"
-#include "communication_helpers/service_tools.hpp"
+#include "rclcpp/rclcpp.hpp"
namespace kuka_drivers_core
{
@@ -37,7 +37,8 @@ bool changeHardwareState(
hw_request->target_state.id = state;
auto hw_response = sendRequest(
client, hw_request, 0, timeout_ms);
- if (!hw_response || !hw_response->ok) {
+ if (!hw_response || !hw_response->ok)
+ {
return false;
}
return true;
@@ -57,7 +58,8 @@ bool changeControllerState(
auto controller_response = sendRequest(
client, controller_request, 0, 2000);
- if (!controller_response || !controller_response->ok) {
+ if (!controller_response || !controller_response->ok)
+ {
return false;
}
return true;
diff --git a/kuka_drivers_core/include/communication_helpers/serialization.hpp b/kuka_drivers_core/include/communication_helpers/serialization.hpp
index 7aa3b96a..3433ad2d 100644
--- a/kuka_drivers_core/include/communication_helpers/serialization.hpp
+++ b/kuka_drivers_core/include/communication_helpers/serialization.hpp
@@ -15,9 +15,9 @@
#ifndef COMMUNICATION_HELPERS__SERIALIZATION_HPP_
#define COMMUNICATION_HELPERS__SERIALIZATION_HPP_
-#include
-#include
#include
+#include
+#include
namespace kuka_drivers_core
{
@@ -32,13 +32,14 @@ int serializeNext(int integer_in, std::vector & serialized_out)
auto from_it = std::prev(serialized_out.end(), sizeof(int));
std::reverse(from_it, serialized_out.end());
// TODO(resizoltan): assert that int is 4 bytes long
- // TODO(resizoltan): check endiannes
+ // TODO(resizoltan): check endianness
return sizeof(int);
}
int deserializeNext(const std::vector & serialized_in, int & integer_out)
{
- if (serialized_in.size() < sizeof(int)) {
+ if (serialized_in.size() < sizeof(int))
+ {
// TODO(resizoltan): error
}
std::vector serialized_copy = serialized_in;
@@ -55,13 +56,14 @@ int serializeNext(double double_in, std::vector & serialized_out)
auto from_it = std::prev(serialized_out.end(), sizeof(double));
std::reverse(from_it, serialized_out.end());
// TODO(resizoltan): assert that int is 4 bytes long
- // TODO(resizoltan): check endiannes
+ // TODO(resizoltan): check endianness
return sizeof(int);
}
int deserializeNext(const std::vector & serialized_in, double & double_out)
{
- if (serialized_in.size() < sizeof(double)) {
+ if (serialized_in.size() < sizeof(double))
+ {
// TODO(resizoltan): error
}
std::vector serialized_copy = serialized_in;
diff --git a/kuka_drivers_core/include/communication_helpers/service_tools.hpp b/kuka_drivers_core/include/communication_helpers/service_tools.hpp
index 03ac7097..c2714ca7 100644
--- a/kuka_drivers_core/include/communication_helpers/service_tools.hpp
+++ b/kuka_drivers_core/include/communication_helpers/service_tools.hpp
@@ -23,16 +23,18 @@
namespace kuka_drivers_core
{
-template
+template
std::future_status wait_for_result(FutureT & future, WaitTimeT time_to_wait)
{
auto end = std::chrono::steady_clock::now() + time_to_wait;
std::chrono::milliseconds wait_period(100);
std::future_status status = std::future_status::timeout;
- do {
+ do
+ {
auto now = std::chrono::steady_clock::now();
auto time_left = end - now;
- if (time_left <= std::chrono::seconds(0)) {
+ if (time_left <= std::chrono::seconds(0))
+ {
break;
}
status = future.wait_for((time_left < wait_period) ? time_left : wait_period);
@@ -40,22 +42,22 @@ std::future_status wait_for_result(FutureT & future, WaitTimeT time_to_wait)
return status;
}
-template
-std::shared_ptr
-sendRequest(
+template
+std::shared_ptr sendRequest(
ClientT client, RequestT request, const uint32_t & service_timeout_ms = 2000,
const uint32_t & response_timeout_ms = 100)
{
- if (service_timeout_ms && !client->wait_for_service(
- std::chrono::milliseconds(service_timeout_ms)))
+ if (
+ service_timeout_ms && !client->wait_for_service(std::chrono::milliseconds(service_timeout_ms)))
{
printf("Wait for service failed\n");
return nullptr;
}
auto future_result = client->async_send_request(request);
- auto future_status = wait_for_result(
- future_result, std::chrono::milliseconds(response_timeout_ms));
- if (future_status != std::future_status::ready) {
+ auto future_status =
+ wait_for_result(future_result, std::chrono::milliseconds(response_timeout_ms));
+ if (future_status != std::future_status::ready)
+ {
printf("Request timed out\n");
return nullptr;
}
diff --git a/kuka_drivers_core/include/kuka_drivers_core/control_mode.hpp b/kuka_drivers_core/include/kuka_drivers_core/control_mode.hpp
index 4a743ba4..01111653 100644
--- a/kuka_drivers_core/include/kuka_drivers_core/control_mode.hpp
+++ b/kuka_drivers_core/include/kuka_drivers_core/control_mode.hpp
@@ -12,15 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-
#ifndef KUKA_DRIVERS_CORE__CONTROL_MODE_HPP_
#define KUKA_DRIVERS_CORE__CONTROL_MODE_HPP_
namespace kuka_drivers_core
{
/**
- * @brief Enum to identify every control mode
- */
+ * @brief Enum to identify every control mode
+ */
enum class ControlMode : std::uint8_t
{
UNSPECIFIED_CONTROL_MODE = 0,
@@ -34,10 +33,9 @@ enum class ControlMode : std::uint8_t
WRENCH_CONTROL = 8,
};
-
/**
- * @brief Enum for identify every type of controllers
- */
+ * @brief Enum for identify every type of controllers
+ */
enum class ControllerType : std::uint8_t
{
JOINT_POSITION_CONTROLLER_TYPE = 0,
diff --git a/kuka_drivers_core/include/kuka_drivers_core/controller_handler.hpp b/kuka_drivers_core/include/kuka_drivers_core/controller_handler.hpp
index 4eeb7850..29feecd9 100644
--- a/kuka_drivers_core/include/kuka_drivers_core/controller_handler.hpp
+++ b/kuka_drivers_core/include/kuka_drivers_core/controller_handler.hpp
@@ -15,14 +15,14 @@
#ifndef KUKA_DRIVERS_CORE__CONTROLLER_HANDLER_HPP_
#define KUKA_DRIVERS_CORE__CONTROLLER_HANDLER_HPP_
-#include
-#include
#include