diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..aafd67c2 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,27 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "github-actions" + # Workflow files stored in the + # default location of `.github/workflows` + directory: "/" + schedule: + interval: "weekly" + - package-ecosystem: "github-actions" + # Workflow files stored in the + # default location of `.github/workflows` + directory: "/" + schedule: + interval: "weekly" + target-branch: "humble" + - package-ecosystem: "github-actions" + # Workflow files stored in the + # default location of `.github/workflows` + directory: "/" + schedule: + interval: "weekly" + target-branch: "iron" diff --git a/.github/workflows/ci-check-docs.yml b/.github/workflows/ci-check-docs.yml new file mode 100644 index 00000000..7d281ca4 --- /dev/null +++ b/.github/workflows/ci-check-docs.yml @@ -0,0 +1,12 @@ +name: Check Docs + +on: + workflow_dispatch: + pull_request: + +jobs: + check-docs: + name: Check Docs + uses: ros-controls/control.ros.org/.github/workflows/reusable-sphinx-check-single-version.yml@master + with: + GAZEBO_ROS2_CONTROL_PR: ${{ github.ref }} diff --git a/.github/workflows/ci-format.yaml b/.github/workflows/ci-format.yaml new file mode 100644 index 00000000..55586aa4 --- /dev/null +++ b/.github/workflows/ci-format.yaml @@ -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-22.04 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: 3.10.6 + - name: Install system hooks + run: sudo apt install -qq cppcheck ament-cmake-uncrustify ament-cmake-pep257 + - uses: pre-commit/action@v3.0.1 + with: + extra_args: --all-files --hook-stage manual diff --git a/.github/workflows/ci-humble.yaml b/.github/workflows/ci-humble.yaml new file mode 100644 index 00000000..e7187a6e --- /dev/null +++ b/.github/workflows/ci-humble.yaml @@ -0,0 +1,83 @@ +name: gazebo_ros2_control CI - Humble + +on: + pull_request: + branches: + - humble + push: + branches: + - humble + +jobs: + build: + runs-on: ubuntu-latest + container: + image: osrf/ros:humble-desktop + steps: + - uses: actions/checkout@v4 + - name: Setup colcon workspace + id: configure + run: | + cd .. + mkdir -p /home/ros2_ws/src + cp -r gazebo_ros2_control /home/ros2_ws/src/ + apt-get update && apt-get upgrade -q -y + apt-get update && apt-get install -q -y --no-install-recommends \ + dirmngr \ + gnupg2 \ + lsb-release \ + python3-colcon-ros + cd /home/ros2_ws/src/ + rosdep update + rosdep install --from-paths ./ -i -y --rosdistro humble \ + --ignore-src + - name: Build project + id: build + run: | + cd /home/ros2_ws/ + . /opt/ros/humble/local_setup.sh + colcon build --packages-up-to gazebo_ros2_control_demos + - name: Run tests + id: test + run: | + cd /home/ros2_ws/ + . /opt/ros/humble/local_setup.sh + colcon test --event-handlers console_direct+ --packages-select gazebo_ros2_control gazebo_ros2_control_demos + colcon test-result + build_testing: + runs-on: ubuntu-latest + container: + image: osrf/ros:humble-desktop + steps: + - uses: actions/checkout@v4 + - name: Setup colcon workspace + id: configure + run: | + cd .. + mkdir -p /home/ros2_ws/src + cp -r gazebo_ros2_control /home/ros2_ws/src/ + curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg + sh -c 'echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2-testing/ubuntu $(lsb_release -cs) main" > /etc/apt/sources.list.d/ros2-latest.list' + apt-get update && apt-get upgrade -q -y + apt-get update && apt-get install -q -y --no-install-recommends \ + dirmngr \ + gnupg2 \ + lsb-release \ + python3-colcon-ros + cd /home/ros2_ws/src/ + rosdep update + rosdep install --from-paths ./ -i -y --rosdistro humble \ + --ignore-src + - name: Build project + id: build + run: | + cd /home/ros2_ws/ + . /opt/ros/humble/local_setup.sh + colcon build --packages-up-to gazebo_ros2_control_demos + - name: Run tests + id: test + run: | + cd /home/ros2_ws/ + . /opt/ros/humble/local_setup.sh + colcon test --event-handlers console_direct+ --packages-select gazebo_ros2_control gazebo_ros2_control_demos + colcon test-result diff --git a/.github/workflows/ci-iron.yaml b/.github/workflows/ci-iron.yaml new file mode 100644 index 00000000..592c9b00 --- /dev/null +++ b/.github/workflows/ci-iron.yaml @@ -0,0 +1,83 @@ +name: gazebo_ros2_control CI - iron + +on: + pull_request: + branches: + - iron + push: + branches: + - iron + +jobs: + build: + runs-on: ubuntu-latest + container: + image: osrf/ros:iron-desktop + steps: + - uses: actions/checkout@v4 + - name: Setup colcon workspace + id: configure + run: | + cd .. + mkdir -p /home/ros2_ws/src + cp -r gazebo_ros2_control /home/ros2_ws/src/ + apt-get update && apt-get upgrade -q -y + apt-get update && apt-get install -q -y --no-install-recommends \ + dirmngr \ + gnupg2 \ + lsb-release \ + python3-colcon-ros + cd /home/ros2_ws/src/ + rosdep update + rosdep install --from-paths ./ -i -y --rosdistro iron \ + --ignore-src + - name: Build project + id: build + run: | + cd /home/ros2_ws/ + . /opt/ros/iron/local_setup.sh + colcon build --packages-up-to gazebo_ros2_control_demos + - name: Run tests + id: test + run: | + cd /home/ros2_ws/ + . /opt/ros/iron/local_setup.sh + colcon test --event-handlers console_direct+ --packages-select gazebo_ros2_control gazebo_ros2_control_demos + colcon test-result + build_testing: + runs-on: ubuntu-latest + container: + image: osrf/ros:iron-desktop + steps: + - uses: actions/checkout@v4 + - name: Setup colcon workspace + id: configure + run: | + cd .. + mkdir -p /home/ros2_ws/src + cp -r gazebo_ros2_control /home/ros2_ws/src/ + curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg + sh -c 'echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2-testing/ubuntu $(lsb_release -cs) main" > /etc/apt/sources.list.d/ros2-latest.list' + apt-get update && apt-get upgrade -q -y + apt-get update && apt-get install -q -y --no-install-recommends \ + dirmngr \ + gnupg2 \ + lsb-release \ + python3-colcon-ros + cd /home/ros2_ws/src/ + rosdep update + rosdep install --from-paths ./ -i -y --rosdistro iron \ + --ignore-src + - name: Build project + id: build + run: | + cd /home/ros2_ws/ + . /opt/ros/iron/local_setup.sh + colcon build --packages-up-to gazebo_ros2_control_demos + - name: Run tests + id: test + run: | + cd /home/ros2_ws/ + . /opt/ros/iron/local_setup.sh + colcon test --event-handlers console_direct+ --packages-select gazebo_ros2_control gazebo_ros2_control_demos + colcon test-result diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci-rolling.yaml similarity index 81% rename from .github/workflows/ci.yaml rename to .github/workflows/ci-rolling.yaml index 4e9f0f1f..096856de 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci-rolling.yaml @@ -1,9 +1,12 @@ -name: Gazebo ros2 control CI +name: gazebo_ros2_control - Rolling on: pull_request: + branches: + - master push: - branches: [ master ] + branches: + - master jobs: build: @@ -11,7 +14,7 @@ jobs: container: image: osrf/ros:rolling-desktop steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup colcon workspace id: configure run: | @@ -46,14 +49,15 @@ jobs: container: image: osrf/ros:rolling-desktop steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup colcon workspace id: configure run: | cd .. mkdir -p /home/ros2_ws/src cp -r gazebo_ros2_control /home/ros2_ws/src/ - sh -c 'echo "deb [arch=$(dpkg --print-architecture)] http://packages.ros.org/ros2-testing/ubuntu $(lsb_release -cs) main" > /etc/apt/sources.list.d/ros2-latest.list' + curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg + sh -c 'echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2-testing/ubuntu $(lsb_release -cs) main" > /etc/apt/sources.list.d/ros2-latest.list' apt-get update && apt-get upgrade -q -y apt-get update && apt-get install -q -y --no-install-recommends \ dirmngr \ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..f03ed362 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,136 @@ +# 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.1.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: v2.31.1 + hooks: + - id: pyupgrade + args: [--py36-plus] + + # # PEP 257 + - repo: local + hooks: + - id: ament_pep257 + name: ament_pep257 + description: Format files with pep257. + entry: ament_pep257 + language: system + args: ["--ignore=D100,D101,D102,D103,D104,D105,D106,D107,D203,D212,D404"] + + - repo: https://github.com/pycqa/flake8 + rev: 4.0.1 + hooks: + - id: flake8 + args: ["--extend-ignore=E501"] + + # CPP hooks + - repo: local + hooks: + - id: ament_uncrustify + name: ament_uncrustify + description: Format files with uncrustify. + entry: ament_uncrustify + language: system + files: \.(c|cc|cxx|cpp|frag|glsl|h|hpp|hxx|ih|ispc|ipp|java|js|m|proto|vert)$ + args: ["--reformat"] + + - repo: local + hooks: + - id: ament_cppcheck + name: ament_cppcheck + description: Static code analysis of C/C++ files. + stages: [commit] + entry: 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 + 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 + 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: 0.10.1 + hooks: + - id: doc8 + args: ['--max-line-length=100', '--ignore=D001'] + exclude: CHANGELOG\.rst$ + + - repo: https://github.com/pre-commit/pygrep-hooks + rev: v1.9.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.1.0 + hooks: + - id: codespell + args: ['--write-changes'] + exclude: CHANGELOG\.rst|\.(svg|pyc)$ diff --git a/README.md b/README.md index aa358e96..b1b8d17d 100644 --- a/README.md +++ b/README.md @@ -1,306 +1,16 @@ # gazebo_ros2_control -This is a ROS 2 package for integrating the `ros2_control` controller architecture with the [Gazebo](http://gazebosim.org/) simulator. +This is a ROS 2 package for integrating the `ros2_control` controller architecture with the [Gazebo Classic](https://classic.gazebosim.org/) simulator. This package provides a Gazebo plugin which instantiates a `ros2_control` controller manager and connects it to a Gazebo model. -# Usage +## Documentation +See the [documentation file](doc/index.rst) or [control.ros.org](https://control.ros.org/master/doc/gazebo_ros2_control/doc/index.html). -This repository contains the contents for testing gazebo_ros2_control +## Build status -It is running Gazebo and some other ROS 2 nodes. - -## Video + Pictures - -![](img/gazebo_ros2_control_position.gif) - -![](img/gazebo_ros2_control_diff_drive.gif) - -## Running - -### Modifying or building your own - -```bash -cd Docker -docker build -t gazebo_ros2_control . -``` - -### To run the demo - -#### Using Docker - -Docker allows us to run the demo without GUI if we don't configure it properly. The following command runs the demo without GUI: - -```bash -docker run -it --rm --name gazebo_ros2_control_demo --net host gazebo_ros2_control ros2 launch gazebo_ros2_control_demos cart_example_position.launch.py gui:=false -``` - -The in your local machine you can run the Gazebo client: - -```bash -gzclient -``` - -#### Using Rocker - -To run the demo with GUI we are going to use [rocker](https://github.com/osrf/rocker/) which is a tool to run docker -images with customized local support injected for things like nvidia support. And user id specific files for cleaner -mounting file permissions. You can install this tool with the following [instructions](https://github.com/osrf/rocker/#installation). - -The following command will launch Gazebo: - -```bash -rocker --x11 --nvidia --name gazebo_ros2_control_demo gazebo_ros2_control:latest -``` - -The following commands allow to move the cart in the rail: - -```bash -docker exec -it gazebo_ros2_control_demo bash -source /home/ros2_ws/install/setup.bash -ros2 run gazebo_ros2_control_demos example_position -``` - - -## Add ros2_control tag to a URDF - -To use `ros2_control` with your robot, you need to add some additional elements to your URDF. -You should include the tag `` to access and control the robot interfaces. We should -include - - - a specific `` for our robot - - `` tag including the robot controllers: commands and states. - -```xml - - - gazebo_ros2_control/GazeboSystem - - - - -1000 - 1000 - - - 1.0 - - - - - -``` - -### Using mimic joints in simulation - -To use `mimic` joints in `gazebo_ros2_control` you should define its parameters to your URDF. -We should include: - -- `` tag to the mimicked joint ([detailed manual](https://wiki.ros.org/urdf/XML/joint)) -- `mimic`, and optional `multiplier`+`offset` parameters to joint definition in `` tag - -As an example, `left_finger_joint` mimics the position of `right_finger_joint` -```xml - - - - - - - - -``` - -```xml - - - - - - - - right_finger_joint - 1 - 0 - - - - - -``` -You can specify a mimicked joint independent of the combination of command interfaces. E.g., if you use an effort command interface for joint 1 but want to let joint 2 mimic the position of joint 1, set -```xml - - - - - - - - right_finger_joint - 1 - 0 - - - - - -``` -Be aware that these mimicked joints do not preserve any conservation of energy, i.e., -the necessary effort of joint 1 won't be changed. - - -## Add the gazebo_ros2_control plugin - -In addition to the `ros2_control` tags, a Gazebo plugin needs to be added to your URDF that -actually parses the `ros2_control` tags and loads the appropriate hardware interfaces and -controller manager. By default the `gazebo_ros2_control` plugin is very simple, though it is also -extensible via an additional plugin architecture to allow power users to create their own custom -robot hardware interfaces between `ros2_control` and Gazebo. - -```xml - - - robot_description - robot_state_publisher - $(find gazebo_ros2_control_demos)/config/cartpole_controller.yaml - - -``` - -The `gazebo_ros2_control` `` tag also has the following optional child elements: - - - ``: The location of the `robot_description` (URDF) on the parameter server, defaults to `robot_description` - - ``: Name of the node where the `robot_param` is located, defauls to `robot_state_publisher` - - ``: YAML file with the configuration of the controllers - -#### Default gazebo_ros2_control Behavior - -By default, without a `` tag, `gazebo_ros2_control` will attempt to get all of the information it needs to interface with a ros2_control-based controller out of the URDF. This is sufficient for most cases, and good for at least getting started. - -The default behavior provides the following ros2_control interfaces: - - - hardware_interface::JointStateInterface - - hardware_interface::EffortJointInterface - - hardware_interface::VelocityJointInterface - -#### Advanced: custom gazebo_ros2_control Simulation Plugins - -The `gazebo_ros2_control` Gazebo plugin also provides a pluginlib-based interface to implement custom interfaces between Gazebo and `ros2_control` for simulating more complex mechanisms (nonlinear springs, linkages, etc). - -These plugins must inherit `gazebo_ros2_control::GazeboSystemInterface` which implements a simulated `ros2_control` -`hardware_interface::SystemInterface`. SystemInterface provides API-level access to read and command joint properties. - -The respective GazeboSystemInterface sub-class is specified in a URDF model and is loaded when the -robot model is loaded. For example, the following XML will load the default plugin: -```xml - - - gazebo_ros2_control/GazeboSystem - - ... - - - - ... - - -``` - -#### Set up controllers - -Use the tag `` inside `` to set the YAML file with the controller configuration. - -```xml - - - $(find gazebo_ros2_control_demos)/config/cartpole_controller.yaml - - -``` - -This controller publishes the state of all resources registered to a -`hardware_interface::StateInterface` to a topic of type `sensor_msgs/msg/JointState`. -The following is a basic configuration of the controller. - -```yaml -joint_state_controller: - ros__parameters: - type: joint_state_controller/JointStateController -``` - -This controller creates an action called `/cart_pole_controller/follow_joint_trajectory` of type `control_msgs::action::FollowJointTrajectory`. - -```yaml -cart_pole_controller: - ros__parameters: - type: joint_trajectory_controller/JointTrajectoryController - joints: - - slider_to_cart - write_op_modes: - - slider_to_cart -``` -#### Executing the examples - -There are some examples in the `gazebo_ros2_control_demos` package. These examples allow to launch a cart in a 30 meter rail. - -![](img/cart.gif) - -You can run some of the configuration running the following commands: - -```bash -ros2 launch gazebo_ros2_control_demos cart_example_position.launch.py -ros2 launch gazebo_ros2_control_demos cart_example_velocity.launch.py -ros2 launch gazebo_ros2_control_demos cart_example_effort.launch.py -ros2 launch gazebo_ros2_control_demos diff_drive.launch.py -ros2 launch gazebo_ros2_control_demos tricycle_drive.launch.py -``` - -Send example commands: - -When the Gazebo world is launched you can run some of the following commads to move the cart. - -```bash -ros2 run gazebo_ros2_control_demos example_position -ros2 run gazebo_ros2_control_demos example_velocity -ros2 run gazebo_ros2_control_demos example_effort -ros2 run gazebo_ros2_control_demos example_diff_drive -ros2 run gazebo_ros2_control_demos example_tricycle_drive -``` - -The following example shows parallel gripper with mimic joint: - -![](img/gripper.gif) - - -```bash -ros2 launch gazebo_ros2_control_demos gripper_mimic_joint_example_position.launch.py -``` - -Send example commands: - -```bash -ros2 run gazebo_ros2_control_demos example_gripper -``` - -To demonstrate the setup of the initial position and a position-mimicked joint in -case of an effort command interface of the joint to be mimicked, run - -```bash -ros2 launch gazebo_ros2_control_demos gripper_mimic_joint_example_effort.launch.py -``` -instead. - - - -#### Gazebo + Moveit2 + ROS 2 - -This example works with [ROS 2 Foxy](https://index.ros.org/doc/ros2/Installation/Foxy/). -You should install Moveit2 from sources, the instructions are available in this [link](https://moveit.ros.org/install-moveit2/source/). - -The repository with all the required packages are in the [gazebo_ros_demos](https://github.com/ros-controls/gazebo_ros_demos/tree/ahcorde/port/ros2). - -```bash -ros2 launch rrbot_moveit_demo_nodes rrbot_demo.launch.py -``` - -![](img/moveit2.gif) +ROS 2 Distro | Branch | Build status | Documentation +:----------: | :----: | :----------: | :-----------: +**Rolling** | [`master`](https://github.com/ros-controls/gazebo_ros2_control/tree/master) | [![Gazebo ros2 control CI](https://github.com/ros-controls/gazebo_ros2_control/actions/workflows/ci-rolling.yaml/badge.svg?branch=master)](https://github.com/ros-controls/gazebo_ros2_control/actions/workflows/ci-rolling.yaml) | [Documentation](https://control.ros.org/master/index.html)
[API Reference](https://control.ros.org/master/doc/api/index.html) +**Iron** | [`iron`](https://github.com/ros-controls/gazebo_ros2_control/tree/iron) | [![Gazebo ros2 control CI](https://github.com/ros-controls/gazebo_ros2_control/actions/workflows/ci-iron.yaml/badge.svg?branch=iron)](https://github.com/ros-controls/gazebo_ros2_control/actions/workflows/ci-iron.yaml) | [Documentation](https://control.ros.org/iron/index.html)
[API Reference](https://control.ros.org/iron/doc/api/index.html) +**Humble** | [`humble`](https://github.com/ros-controls/gazebo_ros2_control/tree/humble) | [![Gazebo ros2 control CI](https://github.com/ros-controls/gazebo_ros2_control/actions/workflows/ci-humble.yaml/badge.svg?branch=humble)](https://github.com/ros-controls/gazebo_ros2_control/actions/workflows/ci-humble.yaml) | [Documentation](https://control.ros.org/humble/index.html)
[API Reference](https://control.ros.org/humble/doc/api/index.html) diff --git a/img/cart.gif b/doc/img/cart.gif similarity index 100% rename from img/cart.gif rename to doc/img/cart.gif diff --git a/img/gazebo_ros2_control_diff_drive.gif b/doc/img/gazebo_ros2_control_diff_drive.gif similarity index 100% rename from img/gazebo_ros2_control_diff_drive.gif rename to doc/img/gazebo_ros2_control_diff_drive.gif diff --git a/img/gazebo_ros2_control_position.gif b/doc/img/gazebo_ros2_control_position.gif similarity index 100% rename from img/gazebo_ros2_control_position.gif rename to doc/img/gazebo_ros2_control_position.gif diff --git a/img/gripper.gif b/doc/img/gripper.gif similarity index 100% rename from img/gripper.gif rename to doc/img/gripper.gif diff --git a/img/moveit2.gif b/doc/img/moveit2.gif similarity index 100% rename from img/moveit2.gif rename to doc/img/moveit2.gif diff --git a/doc/index.rst b/doc/index.rst new file mode 100644 index 00000000..daff5f2c --- /dev/null +++ b/doc/index.rst @@ -0,0 +1,269 @@ +:github_url: https://github.com/ros-controls/gazebo_ros2_control/blob/{REPOS_FILE_BRANCH}/doc/index.rst + +.. _gazebo_ros2_control: + +===================== +gazebo_ros2_control +===================== + +This is a ROS 2 package for integrating the *ros2_control* controller architecture with the `Gazebo Classic `__ simulator. + +This package provides a Gazebo plugin which instantiates a *ros2_control* controller manager and connects it to a Gazebo model. + +.. image:: img/gazebo_ros2_control_position.gif + :alt: Cart + +.. image:: img/gazebo_ros2_control_diff_drive.gif + :alt: DiffBot + +Usage +====== + +Modifying or building your own +--------------------------------- + +.. code-block:: shell + + cd Docker + docker build -t gazebo_ros2_control . + + +To run the demo +--------------------------------- + +1. Using Docker + + Docker allows us to run the demo without GUI if we don't configure it properly. The following command runs the demo without GUI: + + .. code-block:: shell + + docker run -it --rm --name gazebo_ros2_control_demo --net host gazebo_ros2_control ros2 launch gazebo_ros2_control_demos cart_example_position.launch.py gui:=false + + The in your local machine you can run the Gazebo Classic client: + + .. code-block:: shell + + gzclient + +2. Using Rocker + + To run the demo with GUI we are going to use `rocker `__ which is a tool to run docker + images with customized local support injected for things like nvidia support. And user id specific files for cleaner + mounting file permissions. You can install this tool with the following `instructions `__. + + The following command will launch Gazebo Classic: + + .. code-block:: shell + + rocker --x11 --nvidia --name gazebo_ros2_control_demo gazebo_ros2_control:latest + + The following commands allow to move the cart in the rail: + + .. code-block:: shell + + docker exec -it gazebo_ros2_control_demo bash + source /home/ros2_ws/install/setup.bash + ros2 run gazebo_ros2_control_demos example_position + +Add ros2_control tag to a URDF +========================================== + +Simple setup +----------------------------------------------------------- + +To use *ros2_control* with your robot, you need to add some additional elements to your URDF. +You should include the tag ```` to access and control the robot interfaces. We should +include + +* a specific ```` for our robot +* ```` tag including the robot controllers: commands and states. + +.. code-block:: xml + + + + gazebo_ros2_control/GazeboSystem + + + + -1000 + 1000 + + + 1.0 + + + + + + + +Using mimic joints in simulation +----------------------------------------------------------- + +To use ``mimic`` joints in *gazebo_ros2_control* you should define its parameters to your URDF. +We should include: + +* ```` tag to the mimicked joint `detailed manual `__ +* ``mimic`` and ``multiplier`` parameters to joint definition in ```` tag + +.. code-block:: xml + + + + + + + + + + + +.. code-block:: xml + + + right_finger_joint + 1 + + + + + + + +Add the gazebo_ros2_control plugin +========================================== + +In addition to the *ros2_control* tags, a Gazebo plugin needs to be added to your URDF that +actually parses the *ros2_control* tags and loads the appropriate hardware interfaces and +controller manager. By default the *gazebo_ros2_control* plugin is very simple, though it is also +extensible via an additional plugin architecture to allow power users to create their own custom +robot hardware interfaces between *ros2_control* and Gazebo Classic. + +.. code-block:: xml + + + + robot_description + robot_state_publisher + $(find gazebo_ros2_control_demos)/config/cart_controller.yaml + simulation_controller_manager + + + +The *gazebo_ros2_control* ```` tag also has the following optional child elements: + +* ````: The location of the ``robot_description`` (URDF) on the parameter server, defaults to ``robot_description`` +* ````: Name of the node where the ``robot_param`` is located, defaults to ``robot_state_publisher`` +* ````: YAML file with the configuration of the controllers +* ````: if set to true (default), it will hold the joints' position if their interface was not claimed, e.g., the controller hasn't been activated yet. +* ````: Set controller manager name (default: ``controller_manager``) + +Default gazebo_ros2_control Behavior +----------------------------------------------------------- + +By default, without a ```` tag, *gazebo_ros2_control* will attempt to get all of the information it needs to interface with a ros2_control-based controller out of the URDF. This is sufficient for most cases, and good for at least getting started. + +The default behavior provides the following ros2_control interfaces: + +* hardware_interface::JointStateInterface +* hardware_interface::EffortJointInterface +* hardware_interface::VelocityJointInterface + +Advanced: custom gazebo_ros2_control Simulation Plugins +----------------------------------------------------------- + +The *gazebo_ros2_control* Gazebo plugin also provides a pluginlib-based interface to implement custom interfaces between Gazebo Classic and *ros2_control* for simulating more complex mechanisms (nonlinear springs, linkages, etc). + +These plugins must inherit ``gazebo_ros2_control::GazeboSystemInterface`` which implements a simulated *ros2_control* +``hardware_interface::SystemInterface``. SystemInterface provides API-level access to read and command joint properties. + +The respective GazeboSystemInterface sub-class is specified in a URDF model and is loaded when the +robot model is loaded. For example, the following XML will load the default plugin: + +.. code-block:: xml + + + + gazebo_ros2_control/GazeboSystem + + ... + + + + ... + + + + +Set up controllers +----------------------------------------------------------- + +Use the tag ```` inside ```` to set the YAML file with the controller configuration. + +.. code-block:: xml + + + + $(find gazebo_ros2_control_demos)/config/cart_controller.yaml + + + +The following is a basic configuration of the controllers: + +- ``joint_state_broadcaster``: This controller publishes the state of all resources registered to a ``hardware_interface::StateInterface`` to a topic of type ``sensor_msgs/msg/JointState``. + +- ``joint_trajectory_controller``: This controller creates an action called ``/joint_trajectory_controller/follow_joint_trajectory`` of type ``control_msgs::action::FollowJointTrajectory``. + +.. literalinclude:: ../gazebo_ros2_control_demos/config/cart_controller.yaml + :language: yaml + +gazebo_ros2_control_demos +========================================== + +This package contains the contents for testing gazebo_ros2_control. It is running Gazebo Classic and some other ROS 2 nodes. + +There are some examples in the *Gazebo_ros2_control_demos* package. These examples allow to launch a cart in a 30 meter rail. + +.. image:: img/cart.gif + :alt: Cart + +You can run some of the configuration running the following commands: + +.. code-block:: shell + + ros2 launch gazebo_ros2_control_demos cart_example_position.launch.py + ros2 launch gazebo_ros2_control_demos cart_example_velocity.launch.py + ros2 launch gazebo_ros2_control_demos cart_example_effort.launch.py + ros2 launch gazebo_ros2_control_demos diff_drive.launch.py + ros2 launch gazebo_ros2_control_demos tricycle_drive.launch.py + + +When the Gazebo world is launched you can run some of the following commands to move the cart. + +.. code-block:: shell + + ros2 run gazebo_ros2_control_demos example_position + ros2 run gazebo_ros2_control_demos example_velocity + ros2 run gazebo_ros2_control_demos example_effort + ros2 run gazebo_ros2_control_demos example_diff_drive + ros2 run gazebo_ros2_control_demos example_tricycle_drive + + +The following example shows parallel gripper with mimic joint: + +.. image:: img/gripper.gif + :alt: Cart + + +.. code-block:: shell + + ros2 launch gazebo_ros2_control_demos gripper_mimic_joint_example.launch.py + + +Send example commands: + + +.. code-block:: shell + + ros2 run gazebo_ros2_control_demos example_gripper diff --git a/gazebo_ros2_control/CHANGELOG.rst b/gazebo_ros2_control/CHANGELOG.rst index 50de1a39..8eedc4b9 100644 --- a/gazebo_ros2_control/CHANGELOG.rst +++ b/gazebo_ros2_control/CHANGELOG.rst @@ -2,6 +2,61 @@ Changelog for package gazebo_ros2_control ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +0.7.1 (2024-01-24) +------------------ +* Load the URDF to the resource_manager before parsing it to CM (`#262 `_) + * Load the URDF to the resource_manager before parsing it to CM constructor (fixes https://github.com/ros-controls/ros2_control/issues/1299) +* Use lexical casts (`#260 `_) + Co-authored-by: Alejandro Hernández Cordero +* Fix links in documentation (`#263 `_) +* Added controller manager xml argument (`#255 `_) +* Contributors: Alejandro Hernández Cordero, Christoph Fröhlich, Sai Kishor Kothakota, Silvio Traversaro + +0.7.0 (2024-01-04) +------------------ +* Add `hold_joints` parameter (`#251 `_) +* Fix stuck passive joints (`#237 `_) +* Contributors: Christoph Fröhlich, Johannes Huemer + +0.6.2 (2023-08-23) +------------------ +* Catch pluginlib exceptions (`#229 `_) + Co-authored-by: Alejandro Hernández Cordero +* Set the C++ version to 17 (`#221 `_) +* Removed unused var (`#220 `_) +* Remove plugin export from ROS 1 (`#212 `_) +* Forced zero vel in position mode to avoid sagging (`#213 `_) +* Contributors: Alejandro Hernández Cordero, Christoph Fröhlich, gwalck + +0.6.1 (2023-06-09) +------------------ +* Add pre-commit and CI-format (`#206 `_) + * Add pre-commit and ci-format +* Compile with ROS iron and rolling (`#202 `_) +* Contributors: Alejandro Hernández Cordero, Christoph Fröhlich + +0.6.0 (2023-05-23) +------------------ +* add copy operator to SafeEnum (`#197 `_) +* Fixed rolling compilation (`#195 `_) +* Export all dependencies (`#183 `_) (`#184 `_) +* Contributors: Alejandro Hernández Cordero, Noel Jiménez García, Adrian Zwiener + +0.5.1 (2023-02-07) +------------------ +* Various bug fixes (`#177 `_) +* Contributors: AndyZe + +0.5.0 (2023-01-06) +------------------ +* Force setting use_sim_time parameter when using plugin. (`#171 `_) +* Improve error message if robot_description\_ param is wrong (`#168 `_) +* Rename hw info class type to plugin name (`#169 `_) +* Removed warning (`#162 `_) +* Mimic joint should have the same control mode as mimicked joint. (`#154 `_) +* Enable loading params from multiple yaml files (`#149 `_) +* Contributors: Alejandro Hernández Cordero, Christoph Fröhlich, Denis Štogl, Tony Najjar + 0.4.0 (2022-08-09) ------------------ * Implemented perform_command_mode_switch override in GazeboSystem (`#136 `_) diff --git a/gazebo_ros2_control/CMakeLists.txt b/gazebo_ros2_control/CMakeLists.txt index 2440eaf1..cfba1298 100644 --- a/gazebo_ros2_control/CMakeLists.txt +++ b/gazebo_ros2_control/CMakeLists.txt @@ -11,10 +11,12 @@ find_package(pluginlib REQUIRED) find_package(rclcpp REQUIRED) find_package(yaml_cpp_vendor REQUIRED) -# Default to C++14 +# Default to C++17 if(NOT CMAKE_CXX_STANDARD) - set(CMAKE_CXX_STANDARD 14) + set(CMAKE_CXX_STANDARD 17) + set(CMAKE_CXX_STANDARD_REQUIRED ON) endif() + if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-Wall -Wextra -Wconversion -Wno-sign-conversion -Wpedantic -Wnon-virtual-dtor -Woverloaded-virtual) endif() @@ -62,8 +64,18 @@ ament_export_include_directories( include ) -ament_export_dependencies(ament_cmake) -ament_export_dependencies(rclcpp) +ament_export_dependencies( + ament_cmake + angles + controller_manager + gazebo_dev + gazebo_ros + hardware_interface + pluginlib + rclcpp + yaml_cpp_vendor +) + ament_export_libraries( ${PROJECT_NAME} gazebo_hardware_plugins diff --git a/gazebo_ros2_control/README.md b/gazebo_ros2_control/README.md index 0dd9548b..11a61a76 100644 --- a/gazebo_ros2_control/README.md +++ b/gazebo_ros2_control/README.md @@ -1,7 +1,7 @@ # Gazebo ros_control Interfaces This is a ROS 2 package for integrating the [ros2_control](https://github.com/ros-controls/ros2_control) controller architecture -with the [Gazebo](http://gazebosim.org/) simulator. +with the [Gazebo Classic](https://classic.gazebosim.org/) simulator. This package provides a Gazebo plugin which instantiates a ros_control controller manager and connects it to a Gazebo model. diff --git a/gazebo_ros2_control/include/gazebo_ros2_control/gazebo_system_interface.hpp b/gazebo_ros2_control/include/gazebo_ros2_control/gazebo_system_interface.hpp index b0750b07..8a4cf1fb 100644 --- a/gazebo_ros2_control/include/gazebo_ros2_control/gazebo_system_interface.hpp +++ b/gazebo_ros2_control/include/gazebo_ros2_control/gazebo_system_interface.hpp @@ -44,6 +44,7 @@ class SafeEnum : mFlags(original.mFlags) {} ~SafeEnum() = default; + SafeEnum & operator=(const SafeEnum & original) = default; SafeEnum & operator|=(ENUM addValue) {mFlags |= addValue; return *this;} SafeEnum operator|(ENUM addValue) {SafeEnum result(*this); result |= addValue; return result;} SafeEnum & operator&=(ENUM maskValue) {mFlags &= maskValue; return *this;} @@ -60,7 +61,7 @@ class GazeboSystemInterface : public hardware_interface::SystemInterface { public: - /// \brief Initilize the system interface + /// \brief Initialize the system interface /// param[in] model_nh pointer to the ros2 node /// param[in] parent_model pointer to the model /// param[in] control_hardware vector filled with information about robot's control resources diff --git a/gazebo_ros2_control/package.xml b/gazebo_ros2_control/package.xml index 024ec20e..256a7654 100644 --- a/gazebo_ros2_control/package.xml +++ b/gazebo_ros2_control/package.xml @@ -1,7 +1,7 @@ gazebo_ros2_control - 0.4.0 + 0.7.1 gazebo_ros2_control Alejandro Hernandez @@ -34,6 +34,5 @@ ament_cmake - diff --git a/gazebo_ros2_control/src/gazebo_ros2_control_plugin.cpp b/gazebo_ros2_control/src/gazebo_ros2_control_plugin.cpp index 3e4ceab1..6015669a 100644 --- a/gazebo_ros2_control/src/gazebo_ros2_control_plugin.cpp +++ b/gazebo_ros2_control/src/gazebo_ros2_control_plugin.cpp @@ -36,6 +36,8 @@ #include #include #include +#include +#include #include "gazebo_ros/node.hpp" @@ -182,6 +184,27 @@ void GazeboRosControlPlugin::Load(gazebo::physics::ModelPtr parent, sdf::Element } else { impl_->robot_description_node_ = "robot_state_publisher"; // default } + // Hold joints if no control mode is active? + bool hold_joints = true; // default + if (sdf->HasElement("hold_joints")) { + hold_joints = + sdf->GetElement("hold_joints")->Get(); + } + + // Get controller manager node name + std::string controllerManagerNodeName{"controller_manager"}; + + if (sdf->HasElement("controller_manager_name")) { + controllerManagerNodeName = sdf->GetElement("controller_manager_name")->Get(); + } + + // Read urdf from ros parameter server + std::string urdf_string; + urdf_string = impl_->getURDF(impl_->robot_description_); + if (urdf_string.empty()) { + RCLCPP_ERROR_STREAM(impl_->model_nh_->get_logger(), "An empty URDF was passed. Exiting."); + return; + } // There's currently no direct way to set parameters to the plugin's node // So we have to parse the plugin file manually and set it to the node's context. @@ -202,6 +225,12 @@ void GazeboRosControlPlugin::Load(gazebo::physics::ModelPtr parent, sdf::Element impl_->model_nh_->get_logger(), "No parameter file provided. Configuration might be wrong"); } + // set the robot description parameter + // to propagate it among controller manager and controllers + std::string rb_arg = std::string("robot_description:=") + urdf_string; + arguments.push_back(RCL_PARAM_FLAG); + arguments.push_back(rb_arg); + if (sdf->HasElement("ros")) { sdf = sdf->GetElement("ros"); @@ -257,13 +286,10 @@ void GazeboRosControlPlugin::Load(gazebo::physics::ModelPtr parent, sdf::Element std::chrono::duration( impl_->parent_model_->GetWorld()->Physics()->GetMaxStepSize()))); - // Read urdf from ros parameter server then // setup actuators and mechanism control node. // This call will block if ROS is not properly initialized. - std::string urdf_string; std::vector control_hardware_info; try { - urdf_string = impl_->getURDF(impl_->robot_description_); control_hardware_info = hardware_interface::parse_control_resources_from_urdf(urdf_string); } catch (const std::runtime_error & ex) { RCLCPP_ERROR_STREAM( @@ -275,6 +301,13 @@ void GazeboRosControlPlugin::Load(gazebo::physics::ModelPtr parent, sdf::Element std::unique_ptr resource_manager_ = std::make_unique(); + try { + resource_manager_->load_urdf(urdf_string, false, false); + } catch (...) { + // This error should be normal as the resource manager is not supposed to load and initialize + // them + RCLCPP_ERROR(impl_->model_nh_->get_logger(), "Error initializing URDF to resource manager!"); + } try { impl_->robot_hw_sim_loader_.reset( new pluginlib::ClassLoader( @@ -287,11 +320,42 @@ void GazeboRosControlPlugin::Load(gazebo::physics::ModelPtr parent, sdf::Element } for (unsigned int i = 0; i < control_hardware_info.size(); i++) { - std::string robot_hw_sim_type_str_ = control_hardware_info[i].hardware_class_type; - auto gazeboSystem = std::unique_ptr( - impl_->robot_hw_sim_loader_->createUnmanagedInstance(robot_hw_sim_type_str_)); - - rclcpp::Node::SharedPtr node_ros2 = std::dynamic_pointer_cast(impl_->model_nh_); + std::string robot_hw_sim_type_str_ = control_hardware_info[i].hardware_plugin_name; + RCLCPP_DEBUG( + impl_->model_nh_->get_logger(), "Load hardware interface %s ...", + robot_hw_sim_type_str_.c_str()); + std::unique_ptr gazeboSystem; + try { + gazeboSystem = std::unique_ptr( + impl_->robot_hw_sim_loader_->createUnmanagedInstance(robot_hw_sim_type_str_)); + } catch (pluginlib::PluginlibException & ex) { + RCLCPP_ERROR( + impl_->model_nh_->get_logger(), "The plugin failed to load for some reason. Error: %s\n", + ex.what()); + continue; + } + rclcpp::Node::SharedPtr node_ros2 = std::dynamic_pointer_cast( + impl_->model_nh_); + RCLCPP_DEBUG( + impl_->model_nh_->get_logger(), "Loaded hardware interface %s!", + robot_hw_sim_type_str_.c_str()); + try { + node_ros2->declare_parameter("hold_joints", rclcpp::ParameterValue(hold_joints)); + } catch (const rclcpp::exceptions::ParameterAlreadyDeclaredException & e) { + RCLCPP_ERROR( + impl_->model_nh_->get_logger(), "Parameter 'hold_joints' has already been declared, %s", + e.what()); + } catch (const rclcpp::exceptions::InvalidParametersException & e) { + RCLCPP_ERROR( + impl_->model_nh_->get_logger(), "Parameter 'hold_joints' has invalid name, %s", e.what()); + } catch (const rclcpp::exceptions::InvalidParameterValueException & e) { + RCLCPP_ERROR( + impl_->model_nh_->get_logger(), "Parameter 'hold_joints' value is invalid, %s", e.what()); + } catch (const rclcpp::exceptions::InvalidParameterTypeException & e) { + RCLCPP_ERROR( + impl_->model_nh_->get_logger(), "Parameter 'hold_joints' value has wrong type, %s", + e.what()); + } if (!gazeboSystem->initSim( node_ros2, impl_->parent_model_, @@ -302,6 +366,9 @@ void GazeboRosControlPlugin::Load(gazebo::physics::ModelPtr parent, sdf::Element impl_->model_nh_->get_logger(), "Could not initialize robot simulation interface"); return; } + RCLCPP_DEBUG( + impl_->model_nh_->get_logger(), "Initialized robot simulation interface %s!", + robot_hw_sim_type_str_.c_str()); resource_manager_->import_component(std::move(gazeboSystem), control_hardware_info[i]); @@ -320,7 +387,7 @@ void GazeboRosControlPlugin::Load(gazebo::physics::ModelPtr parent, sdf::Element new controller_manager::ControllerManager( std::move(resource_manager_), impl_->executor_, - "controller_manager", + controllerManagerNodeName, impl_->model_nh_->get_namespace())); impl_->executor_->add_node(impl_->controller_manager_); @@ -348,6 +415,9 @@ void GazeboRosControlPlugin::Load(gazebo::physics::ModelPtr parent, sdf::Element " s) is slower than the gazebo simulation period (" << gazebo_period.seconds() << " s)."); } + // Force setting of use_sime_time parameter + impl_->controller_manager_->set_parameter( + rclcpp::Parameter("use_sim_time", rclcpp::ParameterValue(true))); impl_->stop_ = false; auto spin = [this]() @@ -408,7 +478,7 @@ std::string GazeboRosControlPrivate::getURDF(std::string param_name) const RCLCPP_ERROR( model_nh_->get_logger(), "Interrupted while waiting for %s service. Exiting.", robot_description_node_.c_str()); - return 0; + return ""; } RCLCPP_ERROR( model_nh_->get_logger(), "%s service not available, waiting again...", @@ -420,14 +490,13 @@ std::string GazeboRosControlPrivate::getURDF(std::string param_name) const // search and wait for robot_description on param server while (urdf_string.empty()) { - std::string search_param_name; RCLCPP_DEBUG(model_nh_->get_logger(), "param_name %s", param_name.c_str()); try { auto f = parameters_client->get_parameters({param_name}); f.wait(); std::vector values = f.get(); - urdf_string = values[0].as_string(); + urdf_string = values.at(0).as_string(); } catch (const std::exception & e) { RCLCPP_ERROR(model_nh_->get_logger(), "%s", e.what()); } @@ -437,12 +506,12 @@ std::string GazeboRosControlPrivate::getURDF(std::string param_name) const } else { RCLCPP_ERROR( model_nh_->get_logger(), "gazebo_ros2_control plugin is waiting for model" - " URDF in parameter [%s] on the ROS param server.", search_param_name.c_str()); + " URDF in parameter [%s] on the ROS param server.", param_name.c_str()); } - usleep(100000); + std::this_thread::sleep_for(std::chrono::microseconds(100000)); } RCLCPP_INFO( - model_nh_->get_logger(), "Recieved urdf from param server, parsing..."); + model_nh_->get_logger(), "Received urdf from param server, parsing..."); return urdf_string; } diff --git a/gazebo_ros2_control/src/gazebo_system.cpp b/gazebo_ros2_control/src/gazebo_system.cpp index 1303518f..f2f5af43 100644 --- a/gazebo_ros2_control/src/gazebo_system.cpp +++ b/gazebo_ros2_control/src/gazebo_system.cpp @@ -25,6 +25,7 @@ #include "gazebo/sensors/SensorManager.hh" #include "hardware_interface/hardware_info.hpp" +#include "hardware_interface/lexical_casts.hpp" #include "hardware_interface/types/hardware_interface_type_values.hpp" struct MimicJoint @@ -61,6 +62,9 @@ class gazebo_ros2_control::GazeboSystemPrivate /// \brief vector with the control method defined in the URDF for each joint. std::vector joint_control_methods_; + /// \brief vector with indication for actuated joints (vs. passive joints) + std::vector is_joint_actuated_; + /// \brief handles to the joints from within Gazebo std::vector sim_joints_; @@ -102,6 +106,9 @@ class gazebo_ros2_control::GazeboSystemPrivate /// \brief mapping of mimicked joints to index of joint they mimic std::vector mimic_joints_; + + // Should hold the joints if no control_mode is active + bool hold_joints_ = true; }; namespace gazebo_ros2_control @@ -127,6 +134,30 @@ bool GazeboSystem::initSim( return false; } + try { + this->dataPtr->hold_joints_ = this->nh_->get_parameter("hold_joints").as_bool(); + } catch (rclcpp::exceptions::ParameterUninitializedException & ex) { + RCLCPP_ERROR( + this->nh_->get_logger(), + "Parameter 'hold_joints' not initialized, with error %s", ex.what()); + RCLCPP_WARN_STREAM( + this->nh_->get_logger(), "Using default value: " << this->dataPtr->hold_joints_); + } catch (rclcpp::exceptions::ParameterNotDeclaredException & ex) { + RCLCPP_ERROR( + this->nh_->get_logger(), + "Parameter 'hold_joints' not declared, with error %s", ex.what()); + RCLCPP_WARN_STREAM( + this->nh_->get_logger(), "Using default value: " << this->dataPtr->hold_joints_); + } catch (rclcpp::ParameterTypeException & ex) { + RCLCPP_ERROR( + this->nh_->get_logger(), + "Parameter 'hold_joints' has wrong type: %s", ex.what()); + RCLCPP_WARN_STREAM( + this->nh_->get_logger(), "Using default value: " << this->dataPtr->hold_joints_); + } + RCLCPP_DEBUG_STREAM( + this->nh_->get_logger(), "hold_joints (system): " << this->dataPtr->hold_joints_ << std::endl); + registerJoints(hardware_info, parent_model); registerSensors(hardware_info, parent_model); @@ -146,6 +177,7 @@ void GazeboSystem::registerJoints( this->dataPtr->joint_names_.resize(this->dataPtr->n_dof_); this->dataPtr->joint_control_methods_.resize(this->dataPtr->n_dof_); + this->dataPtr->is_joint_actuated_.resize(this->dataPtr->n_dof_); this->dataPtr->joint_position_.resize(this->dataPtr->n_dof_); this->dataPtr->joint_velocity_.resize(this->dataPtr->n_dof_); this->dataPtr->joint_effort_.resize(this->dataPtr->n_dof_); @@ -200,7 +232,7 @@ void GazeboSystem::registerJoints( } auto param_it = joint_info.parameters.find("multiplier"); if (param_it != joint_info.parameters.end()) { - mimic_joint.multiplier = std::stod(joint_info.parameters.at("multiplier")); + mimic_joint.multiplier = hardware_interface::stod(joint_info.parameters.at("multiplier")); } else { mimic_joint.multiplier = 1.0; } @@ -221,14 +253,25 @@ void GazeboSystem::registerJoints( RCLCPP_INFO_STREAM(this->nh_->get_logger(), "\tState:"); - auto get_initial_value = [this](const hardware_interface::InterfaceInfo & interface_info) { + auto get_initial_value = + [this, joint_name](const hardware_interface::InterfaceInfo & interface_info) { + double initial_value{0.0}; if (!interface_info.initial_value.empty()) { - double value = std::stod(interface_info.initial_value); - RCLCPP_INFO(this->nh_->get_logger(), "\t\t\t found initial value: %f", value); - return value; - } else { - return 0.0; + try { + initial_value = hardware_interface::stod(interface_info.initial_value); + RCLCPP_INFO(this->nh_->get_logger(), "\t\t\t found initial value: %f", initial_value); + } catch (std::invalid_argument &) { + RCLCPP_ERROR_STREAM( + this->nh_->get_logger(), + "Failed converting initial_value string to real number for the joint " + << joint_name + << " and state interface " << interface_info.name + << ". Actual value of parameter: " << interface_info.initial_value + << ". Initial value will be set to 0.0"); + throw std::invalid_argument("Failed converting initial_value string"); + } } + return initial_value; }; double initial_position = std::numeric_limits::quiet_NaN(); @@ -313,6 +356,9 @@ void GazeboSystem::registerJoints( this->dataPtr->sim_joints_[j]->SetForce(0, initial_effort); } } + + // check if joint is actuated (has command interfaces) or passive + this->dataPtr->is_joint_actuated_[j] = (joint_info.command_interfaces.size() > 0); } } @@ -495,13 +541,11 @@ GazeboSystem::perform_command_mode_switch( hardware_interface::HW_IF_POSITION)) { this->dataPtr->joint_control_methods_[j] &= static_cast(VELOCITY & EFFORT); - } - if (interface_name == (this->dataPtr->joint_names_[j] + "/" + + } else if (interface_name == (this->dataPtr->joint_names_[j] + "/" + // NOLINT hardware_interface::HW_IF_VELOCITY)) { this->dataPtr->joint_control_methods_[j] &= static_cast(POSITION & EFFORT); - } - if (interface_name == (this->dataPtr->joint_names_[j] + "/" + + } else if (interface_name == (this->dataPtr->joint_names_[j] + "/" + // NOLINT hardware_interface::HW_IF_EFFORT)) { this->dataPtr->joint_control_methods_[j] &= @@ -515,13 +559,11 @@ GazeboSystem::perform_command_mode_switch( hardware_interface::HW_IF_POSITION)) { this->dataPtr->joint_control_methods_[j] |= POSITION; - } - if (interface_name == (this->dataPtr->joint_names_[j] + "/" + + } else if (interface_name == (this->dataPtr->joint_names_[j] + "/" + // NOLINT hardware_interface::HW_IF_VELOCITY)) { this->dataPtr->joint_control_methods_[j] |= VELOCITY; - } - if (interface_name == (this->dataPtr->joint_names_[j] + "/" + + } else if (interface_name == (this->dataPtr->joint_names_[j] + "/" + // NOLINT hardware_interface::HW_IF_EFFORT)) { this->dataPtr->joint_control_methods_[j] |= EFFORT; @@ -601,9 +643,7 @@ hardware_interface::return_type GazeboSystem::write( mimic_joint.offset + mimic_joint.multiplier * this->dataPtr->joint_position_[mimic_joint.mimicked_joint_index]; } - } - - if (this->dataPtr->joint_control_methods_[mimic_joint.joint_index] & VELOCITY) { + } else if (this->dataPtr->joint_control_methods_[mimic_joint.joint_index] & VELOCITY) { if (this->dataPtr->joint_control_methods_[mimic_joint.mimicked_joint_index] & VELOCITY) { // mimic velocity with identical joint_velocity_cmd_ this->dataPtr->joint_velocity_cmd_[mimic_joint.joint_index] = @@ -615,9 +655,7 @@ hardware_interface::return_type GazeboSystem::write( mimic_joint.offset + mimic_joint.multiplier * this->dataPtr->joint_velocity_[mimic_joint.mimicked_joint_index]; } - } - - if (this->dataPtr->joint_control_methods_[mimic_joint.joint_index] & EFFORT) { + } else if (this->dataPtr->joint_control_methods_[mimic_joint.joint_index] & EFFORT) { if (this->dataPtr->joint_control_methods_[mimic_joint.mimicked_joint_index] & EFFORT) { // mimic effort with identical joint_effort_cmd_ this->dataPtr->joint_effort_cmd_[mimic_joint.joint_index] = @@ -636,12 +674,14 @@ hardware_interface::return_type GazeboSystem::write( if (this->dataPtr->sim_joints_[j]) { if (this->dataPtr->joint_control_methods_[j] & POSITION) { this->dataPtr->sim_joints_[j]->SetPosition(0, this->dataPtr->joint_position_cmd_[j], true); - } - if (this->dataPtr->joint_control_methods_[j] & VELOCITY) { + this->dataPtr->sim_joints_[j]->SetVelocity(0, 0.0); + } else if (this->dataPtr->joint_control_methods_[j] & VELOCITY) { // NOLINT this->dataPtr->sim_joints_[j]->SetVelocity(0, this->dataPtr->joint_velocity_cmd_[j]); - } - if (this->dataPtr->joint_control_methods_[j] & EFFORT) { + } else if (this->dataPtr->joint_control_methods_[j] & EFFORT) { // NOLINT this->dataPtr->sim_joints_[j]->SetForce(0, this->dataPtr->joint_effort_cmd_[j]); + } else if (this->dataPtr->is_joint_actuated_[j] && this->dataPtr->hold_joints_) { + // Fallback case is a velocity command of zero (only for actuated joints) + this->dataPtr->sim_joints_[j]->SetVelocity(0, 0.0); } } } diff --git a/gazebo_ros2_control_demos/CHANGELOG.rst b/gazebo_ros2_control_demos/CHANGELOG.rst index d80896d6..86c979fa 100644 --- a/gazebo_ros2_control_demos/CHANGELOG.rst +++ b/gazebo_ros2_control_demos/CHANGELOG.rst @@ -2,6 +2,47 @@ Changelog for package gazebo_ros2_control_demos ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +0.7.1 (2024-01-24) +------------------ + +0.7.0 (2024-01-04) +------------------ +* replace Twist with TwistStamped (`#249 `_) +* Rename cartpole (`#252 `_) + Co-authored-by: Alejandro Hernández Cordero +* Replace double quotes with single ones (`#243 `_) +* Cleanup controller config (`#232 `_) + * Remove wrong yaml entries + * Rename effort_controller +* Contributors: Alejandro Hernández Cordero, Christoph Fröhlich + +0.6.2 (2023-08-23) +------------------ +* Set the C++ version to 17 (`#221 `_) +* Update diff_drive_controller.yaml (`#224 `_) + The wrong base frame is set. The name of the link in the URDF is chassis. +* Contributors: Alejandro Hernández Cordero, David V. Lu!! + +0.6.1 (2023-06-09) +------------------ +* Add pre-commit and CI-format (`#206 `_) + * Add pre-commit and ci-format +* Contributors: Christoph Fröhlich + +0.6.0 (2023-05-23) +------------------ +* Clean shutdown position example (`#196 `_) +* Remove publish_rate parameter (`#179 `_) +* Contributors: Alejandro Hernández Cordero, Tony Najjar + +0.5.1 (2023-02-07) +------------------ + +0.5.0 (2023-01-06) +------------------ +* Add tricycle controller demo (`#145 `_) +* Contributors: Tony Najjar + 0.4.0 (2022-08-09) ------------------ * fix demo launch diff --git a/gazebo_ros2_control_demos/CMakeLists.txt b/gazebo_ros2_control_demos/CMakeLists.txt index 92f49653..6823378a 100644 --- a/gazebo_ros2_control_demos/CMakeLists.txt +++ b/gazebo_ros2_control_demos/CMakeLists.txt @@ -5,9 +5,10 @@ project(gazebo_ros2_control_demos) if(NOT CMAKE_C_STANDARD) set(CMAKE_C_STANDARD 11) endif() -# Default to C++14 +# Default to C++17 if(NOT CMAKE_CXX_STANDARD) - set(CMAKE_CXX_STANDARD 14) + set(CMAKE_CXX_STANDARD 17) + set(CMAKE_CXX_STANDARD_REQUIRED ON) endif() if(NOT WIN32) diff --git a/gazebo_ros2_control_demos/config/cartpole_controller.yaml b/gazebo_ros2_control_demos/config/cart_controller.yaml similarity index 93% rename from gazebo_ros2_control_demos/config/cartpole_controller.yaml rename to gazebo_ros2_control_demos/config/cart_controller.yaml index aa000ca2..f51d2fa5 100644 --- a/gazebo_ros2_control_demos/config/cartpole_controller.yaml +++ b/gazebo_ros2_control_demos/config/cart_controller.yaml @@ -12,7 +12,6 @@ joint_trajectory_controller: ros__parameters: joints: - slider_to_cart - interface_name: position command_interfaces: - position state_interfaces: diff --git a/gazebo_ros2_control_demos/config/cartpole_controller_effort.yaml b/gazebo_ros2_control_demos/config/cart_controller_effort.yaml similarity index 63% rename from gazebo_ros2_control_demos/config/cartpole_controller_effort.yaml rename to gazebo_ros2_control_demos/config/cart_controller_effort.yaml index 8ea3c67c..baf14bc3 100644 --- a/gazebo_ros2_control_demos/config/cartpole_controller_effort.yaml +++ b/gazebo_ros2_control_demos/config/cart_controller_effort.yaml @@ -2,19 +2,13 @@ controller_manager: ros__parameters: update_rate: 100 # Hz - effort_controllers: + effort_controller: type: effort_controllers/JointGroupEffortController joint_state_broadcaster: type: joint_state_broadcaster/JointStateBroadcaster -effort_controllers: +effort_controller: ros__parameters: joints: - slider_to_cart - command_interfaces: - - effort - state_interfaces: - - position - - velocity - - effort diff --git a/gazebo_ros2_control_demos/config/cartpole_controller_velocity.yaml b/gazebo_ros2_control_demos/config/cart_controller_velocity.yaml similarity index 83% rename from gazebo_ros2_control_demos/config/cartpole_controller_velocity.yaml rename to gazebo_ros2_control_demos/config/cart_controller_velocity.yaml index 6a9e240d..cea5cc9e 100644 --- a/gazebo_ros2_control_demos/config/cartpole_controller_velocity.yaml +++ b/gazebo_ros2_control_demos/config/cart_controller_velocity.yaml @@ -15,11 +15,7 @@ velocity_controller: ros__parameters: joints: - slider_to_cart - command_interfaces: - - velocity - state_interfaces: - - position - - velocity + imu_sensor_broadcaster: ros__parameters: sensor_name: cart_imu_sensor diff --git a/gazebo_ros2_control_demos/config/diff_drive_controller.yaml b/gazebo_ros2_control_demos/config/diff_drive_controller.yaml index d14a6e3f..fdc04e13 100644 --- a/gazebo_ros2_control_demos/config/diff_drive_controller.yaml +++ b/gazebo_ros2_control_demos/config/diff_drive_controller.yaml @@ -24,7 +24,7 @@ diff_drive_base_controller: publish_rate: 50.0 odom_frame_id: odom - base_frame_id: base_link + base_frame_id: chassis pose_covariance_diagonal : [0.001, 0.001, 0.0, 0.0, 0.0, 0.01] twist_covariance_diagonal: [0.001, 0.0, 0.0, 0.0, 0.0, 0.01] @@ -33,7 +33,7 @@ diff_drive_base_controller: cmd_vel_timeout: 0.5 #publish_limited_velocity: true - use_stamped_vel: false + use_stamped_vel: true #velocity_rolling_window_size: 10 # Velocity and acceleration limits diff --git a/gazebo_ros2_control_demos/config/tricycle_drive_controller.yaml b/gazebo_ros2_control_demos/config/tricycle_drive_controller.yaml index 3519bfb9..c94b81d5 100644 --- a/gazebo_ros2_control_demos/config/tricycle_drive_controller.yaml +++ b/gazebo_ros2_control_demos/config/tricycle_drive_controller.yaml @@ -13,7 +13,7 @@ joint_state_broadcaster: ros__parameters: extra_joints: ["right_wheel_joint", "left_wheel_joint"] -tricycle_controller: +tricycle_controller: ros__parameters: # Model traction_joint_name: traction_joint # Name of traction joint in URDF @@ -24,14 +24,13 @@ tricycle_controller: # Odometry odom_frame_id: odom base_frame_id: base_link - publish_rate: 50.0 # publish rate of odom and tf open_loop: false # if True, uses cmd_vel instead of hardware interface feedback to compute odometry enable_odom_tf: true # If True, publishes odom<-base_link TF odom_only_twist: false # If True, publishes on /odom only linear.x and angular.z; Useful for computing odometry in another node, e.g robot_localization's ekf pose_covariance_diagonal: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0] # Need to be set if fusing odom with other localization source twist_covariance_diagonal: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0] # Need to be set if fusing odom with other localization source velocity_rolling_window_size: 10 # Rolling window size of rcppmath::RollingMeanAccumulator applied on linear and angular speeds published on odom - + # Rate Limiting traction: # All values should be positive # min_velocity: 0.0 @@ -52,7 +51,7 @@ tricycle_controller: # cmd_vel input cmd_vel_timeout: 500 # In milliseconds. Timeout to stop if no cmd_vel is received - use_stamped_vel: false # Set to True if using TwistStamped. + use_stamped_vel: true # Set to True if using TwistStamped. # Debug publish_ackermann_command: true # Publishes AckermannDrive. The speed does not comply to the msg definition, it the wheel angular speed in rad/s. diff --git a/gazebo_ros2_control_demos/examples/example_diff_drive.cpp b/gazebo_ros2_control_demos/examples/example_diff_drive.cpp index a3c117ff..53b518a2 100644 --- a/gazebo_ros2_control_demos/examples/example_diff_drive.cpp +++ b/gazebo_ros2_control_demos/examples/example_diff_drive.cpp @@ -16,7 +16,7 @@ #include -#include +#include using namespace std::chrono_literals; @@ -27,20 +27,22 @@ int main(int argc, char * argv[]) std::shared_ptr node = std::make_shared("diff_drive_test_node"); - auto publisher = node->create_publisher( - "/diff_drive_base_controller/cmd_vel_unstamped", 10); + auto publisher = node->create_publisher( + "/diff_drive_base_controller/cmd_vel", 10); RCLCPP_INFO(node->get_logger(), "node created"); - geometry_msgs::msg::Twist command; + geometry_msgs::msg::TwistStamped command; - command.linear.x = 0.2; - command.linear.y = 0.0; - command.linear.z = 0.0; + command.header.stamp = node->now(); - command.angular.x = 0.0; - command.angular.y = 0.0; - command.angular.z = 0.1; + command.twist.linear.x = 0.2; + command.twist.linear.y = 0.0; + command.twist.linear.z = 0.0; + + command.twist.angular.x = 0.0; + command.twist.angular.y = 0.0; + command.twist.angular.z = 0.1; while (1) { publisher->publish(command); diff --git a/gazebo_ros2_control_demos/examples/example_effort.cpp b/gazebo_ros2_control_demos/examples/example_effort.cpp index dd4bff8b..ef76a603 100644 --- a/gazebo_ros2_control_demos/examples/example_effort.cpp +++ b/gazebo_ros2_control_demos/examples/example_effort.cpp @@ -29,7 +29,7 @@ int main(int argc, char * argv[]) node = std::make_shared("effort_test_node"); auto publisher = node->create_publisher( - "/effort_controllers/commands", 10); + "/effort_controller/commands", 10); RCLCPP_INFO(node->get_logger(), "node created"); diff --git a/gazebo_ros2_control_demos/examples/example_position.cpp b/gazebo_ros2_control_demos/examples/example_position.cpp index 417a34dc..8d2d4c0b 100644 --- a/gazebo_ros2_control_demos/examples/example_position.cpp +++ b/gazebo_ros2_control_demos/examples/example_position.cpp @@ -149,6 +149,8 @@ int main(int argc, char * argv[]) rclcpp::FutureReturnCode::SUCCESS) { RCLCPP_ERROR(node->get_logger(), "send goal call failed :("); + action_client.reset(); + node.reset(); return 1; } RCLCPP_INFO(node->get_logger(), "send goal call ok :)"); @@ -157,6 +159,8 @@ int main(int argc, char * argv[]) goal_handle = goal_handle_future.get(); if (!goal_handle) { RCLCPP_ERROR(node->get_logger(), "Goal was rejected by server"); + action_client.reset(); + node.reset(); return 1; } RCLCPP_INFO(node->get_logger(), "Goal was accepted by server"); @@ -171,7 +175,8 @@ int main(int argc, char * argv[]) return 1; } - std::cout << "async_send_goal" << std::endl; + action_client.reset(); + node.reset(); rclcpp::shutdown(); return 0; diff --git a/gazebo_ros2_control_demos/examples/example_tricycle_drive.cpp b/gazebo_ros2_control_demos/examples/example_tricycle_drive.cpp index 9713ff76..1783ce1e 100644 --- a/gazebo_ros2_control_demos/examples/example_tricycle_drive.cpp +++ b/gazebo_ros2_control_demos/examples/example_tricycle_drive.cpp @@ -16,7 +16,7 @@ #include -#include +#include using namespace std::chrono_literals; @@ -27,20 +27,22 @@ int main(int argc, char * argv[]) std::shared_ptr node = std::make_shared("tricycle_drive_test_node"); - auto publisher = node->create_publisher( + auto publisher = node->create_publisher( "/tricycle_controller/cmd_vel", 10); RCLCPP_INFO(node->get_logger(), "node created"); - geometry_msgs::msg::Twist command; + geometry_msgs::msg::TwistStamped command; - command.linear.x = 0.2; - command.linear.y = 0.0; - command.linear.z = 0.0; + command.header.stamp = node->now(); - command.angular.x = 0.0; - command.angular.y = 0.0; - command.angular.z = 0.1; + command.twist.linear.x = 0.2; + command.twist.linear.y = 0.0; + command.twist.linear.z = 0.0; + + command.twist.angular.x = 0.0; + command.twist.angular.y = 0.0; + command.twist.angular.z = 0.1; while (1) { publisher->publish(command); diff --git a/gazebo_ros2_control_demos/launch/cart_example_effort.launch.py b/gazebo_ros2_control_demos/launch/cart_example_effort.launch.py index 3e6c91b8..7b0c5036 100644 --- a/gazebo_ros2_control_demos/launch/cart_example_effort.launch.py +++ b/gazebo_ros2_control_demos/launch/cart_example_effort.launch.py @@ -53,17 +53,17 @@ def generate_launch_description(): spawn_entity = Node(package='gazebo_ros', executable='spawn_entity.py', arguments=['-topic', 'robot_description', - '-entity', 'cartpole'], + '-entity', 'cart'], output='screen') - load_joint_state_controller = ExecuteProcess( + load_joint_state_broadcaster = ExecuteProcess( cmd=['ros2', 'control', 'load_controller', '--set-state', 'active', 'joint_state_broadcaster'], output='screen' ) load_joint_trajectory_controller = ExecuteProcess( - cmd=['ros2', 'control', 'load_controller', '--set-state', 'active', 'effort_controllers'], + cmd=['ros2', 'control', 'load_controller', '--set-state', 'active', 'effort_controller'], output='screen' ) @@ -71,12 +71,12 @@ def generate_launch_description(): RegisterEventHandler( event_handler=OnProcessExit( target_action=spawn_entity, - on_exit=[load_joint_state_controller], + on_exit=[load_joint_state_broadcaster], ) ), RegisterEventHandler( event_handler=OnProcessExit( - target_action=load_joint_state_controller, + target_action=load_joint_state_broadcaster, on_exit=[load_joint_trajectory_controller], ) ), diff --git a/gazebo_ros2_control_demos/launch/cart_example_position.launch.py b/gazebo_ros2_control_demos/launch/cart_example_position.launch.py index d5aae851..b741e849 100644 --- a/gazebo_ros2_control_demos/launch/cart_example_position.launch.py +++ b/gazebo_ros2_control_demos/launch/cart_example_position.launch.py @@ -53,10 +53,10 @@ def generate_launch_description(): spawn_entity = Node(package='gazebo_ros', executable='spawn_entity.py', arguments=['-topic', 'robot_description', - '-entity', 'cartpole'], + '-entity', 'cart'], output='screen') - load_joint_state_controller = ExecuteProcess( + load_joint_state_broadcaster = ExecuteProcess( cmd=['ros2', 'control', 'load_controller', '--set-state', 'active', 'joint_state_broadcaster'], output='screen' @@ -72,12 +72,12 @@ def generate_launch_description(): RegisterEventHandler( event_handler=OnProcessExit( target_action=spawn_entity, - on_exit=[load_joint_state_controller], + on_exit=[load_joint_state_broadcaster], ) ), RegisterEventHandler( event_handler=OnProcessExit( - target_action=load_joint_state_controller, + target_action=load_joint_state_broadcaster, on_exit=[load_joint_trajectory_controller], ) ), diff --git a/gazebo_ros2_control_demos/launch/cart_example_velocity.launch.py b/gazebo_ros2_control_demos/launch/cart_example_velocity.launch.py index c155e34a..ea853dee 100644 --- a/gazebo_ros2_control_demos/launch/cart_example_velocity.launch.py +++ b/gazebo_ros2_control_demos/launch/cart_example_velocity.launch.py @@ -52,10 +52,10 @@ def generate_launch_description(): spawn_entity = Node(package='gazebo_ros', executable='spawn_entity.py', arguments=['-topic', 'robot_description', - '-entity', 'cartpole'], + '-entity', 'cart'], output='screen') - load_joint_state_controller = ExecuteProcess( + load_joint_state_broadcaster = ExecuteProcess( cmd=['ros2', 'control', 'load_controller', '--set-state', 'active', 'joint_state_broadcaster'], output='screen' @@ -75,12 +75,12 @@ def generate_launch_description(): RegisterEventHandler( event_handler=OnProcessExit( target_action=spawn_entity, - on_exit=[load_joint_state_controller], + on_exit=[load_joint_state_broadcaster], ) ), RegisterEventHandler( event_handler=OnProcessExit( - target_action=load_joint_state_controller, + target_action=load_joint_state_broadcaster, on_exit=[load_joint_trajectory_controller], ) ), diff --git a/gazebo_ros2_control_demos/launch/diff_drive.launch.py b/gazebo_ros2_control_demos/launch/diff_drive.launch.py index 97913bde..faa476db 100644 --- a/gazebo_ros2_control_demos/launch/diff_drive.launch.py +++ b/gazebo_ros2_control_demos/launch/diff_drive.launch.py @@ -56,7 +56,7 @@ def generate_launch_description(): '-entity', 'diffbot'], output='screen') - load_joint_state_controller = ExecuteProcess( + load_joint_state_broadcaster = ExecuteProcess( cmd=['ros2', 'control', 'load_controller', '--set-state', 'active', 'joint_state_broadcaster'], output='screen' @@ -72,12 +72,12 @@ def generate_launch_description(): RegisterEventHandler( event_handler=OnProcessExit( target_action=spawn_entity, - on_exit=[load_joint_state_controller], + on_exit=[load_joint_state_broadcaster], ) ), RegisterEventHandler( event_handler=OnProcessExit( - target_action=load_joint_state_controller, + target_action=load_joint_state_broadcaster, on_exit=[load_diff_drive_base_controller], ) ), diff --git a/gazebo_ros2_control_demos/launch/gripper_mimic_joint_example_effort.launch.py b/gazebo_ros2_control_demos/launch/gripper_mimic_joint_example_effort.launch.py index 49262dad..a016c2f9 100644 --- a/gazebo_ros2_control_demos/launch/gripper_mimic_joint_example_effort.launch.py +++ b/gazebo_ros2_control_demos/launch/gripper_mimic_joint_example_effort.launch.py @@ -57,7 +57,7 @@ def generate_launch_description(): '-entity', 'gripper'], output='screen') - load_joint_state_controller = ExecuteProcess( + load_joint_state_broadcaster = ExecuteProcess( cmd=['ros2', 'control', 'load_controller', '--set-state', 'active', 'joint_state_broadcaster'], output='screen' @@ -73,12 +73,12 @@ def generate_launch_description(): RegisterEventHandler( event_handler=OnProcessExit( target_action=spawn_entity, - on_exit=[load_joint_state_controller], + on_exit=[load_joint_state_broadcaster], ) ), RegisterEventHandler( event_handler=OnProcessExit( - target_action=load_joint_state_controller, + target_action=load_joint_state_broadcaster, on_exit=[load_gripper_controller], ) ), diff --git a/gazebo_ros2_control_demos/launch/tricycle_drive.launch.py b/gazebo_ros2_control_demos/launch/tricycle_drive.launch.py index f9a905fe..a857248a 100644 --- a/gazebo_ros2_control_demos/launch/tricycle_drive.launch.py +++ b/gazebo_ros2_control_demos/launch/tricycle_drive.launch.py @@ -56,7 +56,7 @@ def generate_launch_description(): '-entity', 'tricycle'], output='screen') - load_joint_state_controller = ExecuteProcess( + load_joint_state_broadcaster = ExecuteProcess( cmd=['ros2', 'control', 'load_controller', '--set-state', 'active', 'joint_state_broadcaster'], output='screen' @@ -69,25 +69,25 @@ def generate_launch_description(): ) rviz = Node( - package="rviz2", - executable="rviz2", + package='rviz2', + executable='rviz2', arguments=[ - "-d", - os.path.join(gazebo_ros2_control_demos_path, "config/config.rviz"), + '-d', + os.path.join(gazebo_ros2_control_demos_path, 'config/config.rviz'), ], - output="screen", + output='screen', ) return LaunchDescription([ RegisterEventHandler( event_handler=OnProcessExit( target_action=spawn_entity, - on_exit=[load_joint_state_controller], + on_exit=[load_joint_state_broadcaster], ) ), RegisterEventHandler( event_handler=OnProcessExit( - target_action=load_joint_state_controller, + target_action=load_joint_state_broadcaster, on_exit=[load_tricycle_controller], ) ), diff --git a/gazebo_ros2_control_demos/package.xml b/gazebo_ros2_control_demos/package.xml index 421c441f..497fda86 100644 --- a/gazebo_ros2_control_demos/package.xml +++ b/gazebo_ros2_control_demos/package.xml @@ -1,7 +1,7 @@ gazebo_ros2_control_demos - 0.4.0 + 0.7.1 gazebo_ros2_control_demos Alejandro Hernandez @@ -38,7 +38,6 @@ launch_ros robot_state_publisher ros2_control - ros2_controllers rclcpp std_msgs velocity_controllers diff --git a/gazebo_ros2_control_demos/urdf/test_cart_effort.xacro.urdf b/gazebo_ros2_control_demos/urdf/test_cart_effort.xacro.urdf index 523bca36..35d13c12 100644 --- a/gazebo_ros2_control_demos/urdf/test_cart_effort.xacro.urdf +++ b/gazebo_ros2_control_demos/urdf/test_cart_effort.xacro.urdf @@ -1,9 +1,5 @@ - - - - - + @@ -68,7 +64,7 @@ - $(find gazebo_ros2_control_demos)/config/cartpole_controller_effort.yaml + $(find gazebo_ros2_control_demos)/config/cart_controller_effort.yaml diff --git a/gazebo_ros2_control_demos/urdf/test_cart_position.xacro.urdf b/gazebo_ros2_control_demos/urdf/test_cart_position.xacro.urdf index be1829d0..8ab12f82 100644 --- a/gazebo_ros2_control_demos/urdf/test_cart_position.xacro.urdf +++ b/gazebo_ros2_control_demos/urdf/test_cart_position.xacro.urdf @@ -1,9 +1,5 @@ - - - - - + @@ -67,7 +63,7 @@ - $(find gazebo_ros2_control_demos)/config/cartpole_controller.yaml + $(find gazebo_ros2_control_demos)/config/cart_controller.yaml diff --git a/gazebo_ros2_control_demos/urdf/test_cart_velocity.xacro.urdf b/gazebo_ros2_control_demos/urdf/test_cart_velocity.xacro.urdf index 08e28d1b..09939e8d 100644 --- a/gazebo_ros2_control_demos/urdf/test_cart_velocity.xacro.urdf +++ b/gazebo_ros2_control_demos/urdf/test_cart_velocity.xacro.urdf @@ -1,9 +1,5 @@ - - - - - + @@ -97,7 +93,7 @@ - $(find gazebo_ros2_control_demos)/config/cartpole_controller_velocity.yaml + $(find gazebo_ros2_control_demos)/config/cart_controller_velocity.yaml