Unverified Commit 4888549d authored by Denis Štogl's avatar Denis Štogl Committed by GitHub
Browse files

Use Arguments in launch files and enable their reuse. (#76)



* Add correction to rrbot launch using arguments and reuse the main file for starting examples.

* Rename config package name

* Reorder packages and start docs. Not tested yet.

* Update lauch and description files to updated structure

* Move all files

* Corrected launch of position_only example

* Make multiple_interfaces works on branch add-rrbot-corrections. (#101)

* Fix wrong macro in rrbot_system_multi_interface.urdf

* First correction to README.md (forward_command_controller_position)

* Bump ros2 CI actions to 2 for setup-ros
Co-authored-by: Olivier Stasse's avatarOlivier Stasse <olivier.stasse@laas.fr>

* Update readme and test rrbot examples.

* Add also DiffBot working

* Update README.md
Co-authored-by: default avatarJordan Palacios <j.palacios1986@gmail.com>

* Apply suggestions from code review
Co-authored-by: default avatarmahaarbo <mahaarbo@users.noreply.github.com>
Co-authored-by: default avatarKarsten Knese <Karsten1987@users.noreply.github.com>

* Add rrbot corrections following review of @jordan-palacios (#104)

* Implement classical differential wheel robot.
* Add rviz configuration file.
Co-authored-by: Olivier Stasse's avatarOlivier Stasse <olivier.stasse@laas.fr>
Co-authored-by: default avatarDenis Štogl <destogl@users.noreply.github.com>

* Update README.md
Co-authored-by: default avatarmahaarbo <mahaarbo@users.noreply.github.com>
Co-authored-by: Olivier Stasse's avatarOlivier Stasse <ostasse@laas.fr>
Co-authored-by: Olivier Stasse's avatarOlivier Stasse <olivier.stasse@laas.fr>
Co-authored-by: default avatarJordan Palacios <j.palacios1986@gmail.com>
Co-authored-by: default avatarmahaarbo <mahaarbo@users.noreply.github.com>
Co-authored-by: default avatarKarsten Knese <Karsten1987@users.noreply.github.com>
parent f5e163d4
......@@ -15,7 +15,7 @@ jobs:
strategy:
fail-fast: false
steps:
- uses: ros-tooling/setup-ros@0.0.26
- uses: ros-tooling/setup-ros@v0.2
with:
required-ros-distributions: foxy
- uses: ros-tooling/action-ros-ci@v0.2
......@@ -24,7 +24,8 @@ jobs:
# build all packages listed in the meta package
package-name:
ros2_control_demo_hardware
ros2_control_demo_robot
ros2_control_demo_description
ros2_control_demo_bringup
ros2_control_demos
vcs-repo-file-url: |
https://raw.githubusercontent.com/${{ github.repository }}/${{ github.sha }}/ros2_control_demos.repos
......
......@@ -14,14 +14,15 @@ jobs:
strategy:
fail-fast: false
steps:
- uses: ros-tooling/setup-ros@0.0.26
- uses: ros-tooling/setup-ros@v0.2
- uses: ros-tooling/action-ros-ci@v0.2
with:
target-ros2-distro: foxy
# build all packages listed in the meta package
package-name:
ros2_control_demo_hardware
ros2_control_demo_robot
ros2_control_demo_description
ros2_control_demo_bringup
ros2_control_demos
vcs-repo-file-url: |
https://raw.githubusercontent.com/ros2/ros2/foxy/ros2.repos
......
......@@ -12,14 +12,15 @@ jobs:
linter: [copyright, cppcheck, lint_cmake]
steps:
- uses: actions/checkout@v1
- uses: ros-tooling/setup-ros@v0.1
- uses: ros-tooling/setup-ros@v0.2
- uses: ros-tooling/action-ros-lint@v0.1
with:
distribution: foxy
linter: ${{ matrix.linter }}
package-name:
ros2_control_demo_hardware
ros2_control_demo_robot
ros2_control_demo_description
ros2_control_demo_bringup
ros2_control_demos
ament_lint_cpplint:
......@@ -31,7 +32,7 @@ jobs:
linter: [cpplint]
steps:
- uses: actions/checkout@v1
- uses: ros-tooling/setup-ros@v0.1
- uses: ros-tooling/setup-ros@v0.2
- uses: ros-tooling/action-ros-lint@v0.1
with:
distribution: foxy
......@@ -39,5 +40,6 @@ jobs:
arguments: "--filter=-whitespace/newline"
package-name:
ros2_control_demo_hardware
ros2_control_demo_robot
ros2_control_demo_description
ros2_control_demo_bringup
ros2_control_demos
......@@ -19,32 +19,37 @@ The repository has three goals:
The repository is inspired by the [ros_control_boilerplate](https://github.com/PickNikRobotics/ros_control_boilerplate) repository from Dave Coleman.
The simulation has three parts/packages:
1. The first package, `ros2_control_demo_hardware`, implements the hardware interfaces described in the roadmap.
1. The first package, `ros2_control_demo_bringup`, holds launch files and runtime configurations for demo robots.
2. The second package, `ros2_control_demo_description`, stored URDF-description files, rviz configurations and meshes for the demo robots.
3. The third package, `ros2_control_demo_hardware`, implements the hardware interfaces described in the roadmap.
The examples simulate a simple *RRbot* internally to provide sufficient test and demonstration data and reduce external dependencies.
This package does not have any dependencies except `ros2` core packages and can, therefore, be used on SoC-hardware of headless systems.
2. The second package, `ros2_control_demo_hardware_gazebo`, uses a Gazebo simulator to simulate the *RRBot* and its physics.
This package is useful to test the connection of `ros2_control` to the Gazebo simulator and to detect any missing plugins.
3. The third package `ros2_control_demo_robot` holds examples for *RRbot* URDF-description, launch files and controllers.
This repository demonstrates the following `ros2_control` concepts:
* Creating of `*HardwareInterface` for a System, Sensor, and Actuator.
* Creating a robot description in the form of URDF files
* Loading the configuration and starting a robot using launch files
* Control of two joints of *RRBot*
* Using simulated robots and starting `ros_control` with Gazebo simulator
* Implementing of controller switching strategy for a robot
* Using joint limits and transmission concepts in `ros2_control`
* Creating a `*HardwareInterface` for a System, Sensor, and Actuator.
* Creating a robot description in the form of URDF files.
* Loading the configuration and starting a robot using launch files.
* Control of two joints of *RRBot*.
* Using simulated robots and starting `ros2_control` with Gazebo simulator.
* Implementing a controller switching strategy for a robot.
* Using joint limits and transmission concepts in `ros2_control`.
## Quick Hints
These are some quick hints, especially for those coming from a ROS1 control background:
* There are now three categories of hardware interface: *Sensor*, *Actuator*, and *System*. Sensor is for individual sensors; Actuator is for individual actuators; System is for any combination of multiple sensors/actuators. You could think of a Sensor as read-only.
* ros(1)_control only allowed three hardware interface types: position, velocity, and effort. ros2_control allows you to create any interface type by defining a custom string. For example, you might define a `position_in_degrees` or a `temperature` interface. The most common (position, velocity, acceleration, effort) are already defined as constants in hardware_interface/types/hardware_interface_type_values.hpp.
* In ros2_control, all parameters for the driver are specified in the URDF. The ros2_control framework uses the <ros2_control> tag in the URDF.
* <ros2_control> tags in the URDF must be compatible with the controller's configuration.
* PLUGINLIB_EXPORT_CLASS macro is required when implementing an interface.
* There are now three categories of hardware components: *Sensor*, *Actuator*, and *System*.
*Sensor* is for individual sensors; *Actuator* is for individual actuators; *System* is for any combination of multiple sensors/actuators.
You could think of a Sensor as read-only.
All components are used as plugins and therefore exported using `PLUGINLIB_EXPORT_CLASS` macro.
* *ros(1)_control* only allowed three hardware interface types: position, velocity, and effort.
*ros2_control* allows you to create any interface type by defining a custom string. For example, you might define a `position_in_degrees` or a `temperature` interface.
The most common (position, velocity, acceleration, effort) are already defined as constants in hardware_interface/types/hardware_interface_type_values.hpp.
* Joint names in <ros2_control> tags in the URDF must be compatible with the controller's configuration.
* In ros2_control, all parameters for the driver are specified in the URDF.
The ros2_control framework uses the **<ros2_control>** tag in the URDF.
* Joint names in <ros2_control> tags in the URDF must be compatible with the controller's configuration.
# Build from source
```
......@@ -53,8 +58,9 @@ git clone https://github.com/ros-controls/ros2_controllers
git clone https://github.com/ros-controls/ros2_control_demos
```
**NOTE**: `ros2_control` and `ros2_controllers` packages are released for foxy and can be installed using package manager.
For daily use it is recommended to use the released version but there may always be some not-yet-released changes that are required to build the demos.
**NOTE**: `ros2_control` and `ros2_controllers` packages are released for foxy and can be installed using a package manager.
We provide officially released and maintained debian packages, which can easily be installed via aptitude.
However, there might be cases in which not-yet released demos or features are only available through a source build in your own workspace.
* Install dependencies (maybe you need `sudo`):
```
......@@ -71,7 +77,7 @@ git clone https://github.com/ros-controls/ros2_control_demos
# Getting Started with ros2_control
Each of the described example cases from the roadmap has its own launch and URDF file.
Each of the described example cases from the [roadmap](https://github.com/ros-controls/roadmap/blob/master/design_drafts/components_architecture_and_urdf_examples.md) has its own launch and URDF file.
## Starting example robots
......@@ -80,22 +86,23 @@ Each example is started with a single launch file which starts up the robot hard
The `rviz2` setup can be recreated following these steps:
- The robot models can be visualized using `RobotModel` display using `/robot_description` topic.
- Or you can simply open the configuration from `rviz` folder in `ros2_control_demo_robot` package manually or directly by executing:
- Or you can simply open the configuration from `rviz` folder in `ros2_control_demo_description` package manually or directly by executing:
```
rviz2 --display-config `ros2 pkg prefix ros2_control_demo_robot`/share/ros2_control_demo_robot/rviz/rrbot.rviz
rviz2 --display-config `ros2 pkg prefix ros2_control_demo_description`/share/ros2_control_demo_description/rviz/rrbot.rviz
```
*RRBot*, or ''Revolute-Revolute Manipulator Robot'', is a simple 3-linkage, 2-joint arm that we will use to demonstrate various features. It essentially a double inverted pendulum and demonstrates some fun control concepts within a simulator and was originally introduced for Gazebo tutorials.
The *RRbot* URDF files can be found in the `description` folder of `ros2_control_demo_robot` package.
*RRBot*, or ''Revolute-Revolute Manipulator Robot'', is a simple 3-linkage, 2-joint arm that we will use to demonstrate various features.
It is essentially a double inverted pendulum and demonstrates some fun control concepts within a simulator and was originally introduced for Gazebo tutorials.
The *RRBot* URDF files can be found in the `urdf` folder of `ros2_control_demo_description` package.
### Example 1: "Industrial Robots with only one interface"
### General notes about examples
1. Open another terminal and start the roslaunch file:
1. To start an example open a terminal, source your ROS2-workspace and execute a launch file with:
```
ros2 launch ros2_control_demo_robot rrbot_system_position_only.launch.py
ros2 launch ros2_control_demo_bringup <example_launch_file>
```
2. Open another terminal and check that `RRBotSystemPositionOnlyHardware` loaded properly:
2. To check if the hardware interface loaded properly, open another terminal and execute:
```
ros2 control list_hardware_interfaces
```
......@@ -109,7 +116,108 @@ The *RRbot* URDF files can be found in the `description` folder of `ros2_control
joint2/position
```
## Controlles and moving hardware
3. Check which controllers are running using:
```
ros2 control list_controllers
```
You should get something like:
```
forward_position_controller[forward_command_controller/ForwardCommandController] unconfigured
joint_state_broadcaster[joint_state_broadcaster/JointStateBroadcaster] active
```
4. Check [Controllers and moving hardware](#Controlles-and-moving-hardware) section to move *RRBot*.
### Example 1: "Industrial Robots with only one interface"
- Launch file: rrbot_system_position_only.launch.py
- Command interfaces:
- joint1/position
- joint2/position
- State interfaces:
- joint1/position
- joint2/position
Available controllers:
- `joint_state_broadcaster[joint_state_broadcaster/JointStateBroadcaster]`
- `forward_position_controller[forward_command_controller/ForwardCommandController]` (position)
Available launch-file options:
- `use_fake_hardware:=true` - start `FakeSystem` instead of hardware.
This is a simple simulation that mimics joint command to their states.
This is useful to test *ros2_control* integration and controllers without physical hardware.
### Example 2: "Industrial Robots with only one interface" (Gazebo simulation)
- **TBA**
### Example 3: "Robots with multiple interfaces"
- Launch file: rrbot_system_multi_interface.launch.py
- Command interfaces:
- joint1/position
- joint2/position
- joint1/velocity
- joint2/velocity
- joint1/acceleration
- joint2/acceleration
- State interfaces:
- joint1/position
- joint2/position
- joint1/velocity
- joint2/velocity
- joint1/acceleration
- joint2/acceleration
Available controllers:
- `joint_state_broadcaster[joint_state_broadcaster/JointStateBroadcaster]`
- `forward_position_controller[position_controllers/JointGroupPositionController]`
- `forward_velocity_controller[velocity_controllers/JointGroupVelocityController]`
- `forward_acceleration_controller[forward_command_controller/ForwardCommandController]`
- `forward_illegal1_controller[forward_command_controller/ForwardCommandController]`
- `forward_illegal2_controller[forward_command_controller/ForwardCommandController]`
Notes:
- The example shows how to implement multi-interface robot hardware taking care about interfaces used.
The two illegal controllers demonstrate how hardware interface declines faulty claims to access joint command interfaces.
### Example 4: "Differential drive mobile robot"
- Launch file: diffbot_system.launch.py
- Command interfaces:
- left_wheel_joint/velocity
- right_wheel_joint/velocity
- State interfaces:
- left_wheel_joint/position
- left_wheel_joint/velocity
- right_wheel_joint/position
- right_wheel_joint/velocity
Available controllers:
- `joint_state_broadcaster[joint_state_broadcaster/JointStateBroadcaster]`
- `diffbot_base_controller[diff_drive_controller/DiffDriveController] active`
Sending commands to diff drive controller:
```
ros2 topic pub --rate 30 /diffbot_base_controller/cmd_vel_unstamped geometry_msgs/msg/Twist "linear:
x: 0.7
y: 0.0
z: 0.0
angular:
x: 0.0
y: 0.0
z: 1.0"
```
You should now see an orange box circling in `rviz2`.
## Controllers and moving hardware
To move the robot you should load and start controllers.
The `JointStateController` is used to publish the joint states to ROS topics.
Direct joint commands are sent to this robot via the `ForwardCommandController`.
......@@ -121,7 +229,7 @@ Check the [Results](##result) section on how to ensure that things went well.
Open another terminal and load, configure and start `joint_state_controller`:
```
ros2 control load_start_controller joint_state_controller
ros2 control set_controller_state joint_state_controller start
```
Check if controller is loaded properly:
```
......@@ -137,9 +245,18 @@ Now you should also see the *RRbot* represented correctly in `rviz2`.
### Using ForwardCommandController
1. If you want to test hardware with `ForwardCommandController` first load and configure it:
1. If you want to test hardware with `ForwardCommandController` first load a controller (not always needed):
```
ros2 control load_configure_controller forward_position_controller
ros2 control load_controller forward_position_controller
```
Check if the controller is loaded properly:
```
ros2 control list_controllers
```
2. Then configure it:
```
ros2 control set_controller_state forward_position_controller configure
```
Check if the controller is loaded properly:
```
......@@ -147,13 +264,12 @@ Now you should also see the *RRbot* represented correctly in `rviz2`.
```
You should get the response:
```
joint_state_controller[joint_state_controller/JointStateController] active
forward_position_controller[forward_command_controller/ForwardCommandController] inactive
```
2. Now start the controller:
```
ros2 control switch_controllers --start-controllers forward_position_controller
ros2 control switch_controllers --start forward_position_controller
```
Check if controllers are activated:
```
......@@ -165,9 +281,7 @@ Now you should also see the *RRbot* represented correctly in `rviz2`.
forward_position_controller[forward_command_controller/ForwardCommandController] active
```
**NOTE**: You can do this in only one step by using `load_start_controller` verb instead of `load_configure_controller`.
3. Send command to the controller, either:
3. Send a command to the controller, either:
a. Manually using ros2 cli interface:
```
......@@ -175,9 +289,9 @@ Now you should also see the *RRbot* represented correctly in `rviz2`.
- 0.5
- 0.5"
```
b. Or you can start demo node which sends two goals every 5 seconds in a loop:
B. Or you can start a demo node which sends two goals every 5 seconds in a loop:
```
ros2 launch ros2_control_test_nodes rrbot_test_forward_position_controller.launch.py
ros2 launch ros2_control_demo_bringup test_forward_position_controller.launch.py
```
## Result
......
......@@ -5,6 +5,16 @@ Demos
This repository provides templates for the development of ros2_control-enabled robots and a simple simulations to demonstrate and prove ros2_control concepts.
Repository organization
^^^^^^^^^^^^^^^^^^^^^^^
**Note:** the following list is comprehensive.
The repository is organized in the following packages:
- ``ros2_control_demo_hardware`` - implementation of example hardware interfaces,
- ``ros2_control_demo_bringup`` - nodes starting hardware interfaces, controllers and GUIs.
- ``ros2_control_test_node`` - nodes for testing ros2_control-enabled robots and their integration in the framework.
Mode switching demo
^^^^^^^^^^^^^^^^^^^
......@@ -13,7 +23,7 @@ Start up the multi interface rrbot system:
.. code-block:: bash
ros2 launch ros2_control_demo_robot rrbot_system_multi_interface.launch.py
ros2 launch ros2_control_demo_bringup rrbot_system_multi_interface.launch.py
List the available interfaces
......
cmake_minimum_required(VERSION 3.5)
project(ros2_control_demo_robot)
project(ros2_control_demo_bringup)
# Default to C++14
if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 14)
endif()
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra)
endif()
# find dependencies
find_package(ament_cmake REQUIRED)
## INSTALL
install(
DIRECTORY config description launch rviz
DIRECTORY config launch
DESTINATION share/${PROJECT_NAME}
)
if(BUILD_TESTING)
find_package(ament_cmake_gtest REQUIRED)
endif()
ament_environment_hooks("${CMAKE_CURRENT_SOURCE_DIR}/env-hooks/${PROJECT_NAME}.dsv.in")
## EXPORTS
ament_package()
controller_manager:
ros__parameters:
update_rate: 2 # Hz
update_rate: 100 # Hz
joint_state_broadcaster:
type: joint_state_broadcaster/JointStateBroadcaster
......
......@@ -2,8 +2,8 @@ controller_manager:
ros__parameters:
update_rate: 2 # Hz
joint_state_controller:
type: joint_state_controller/JointStateController
joint_state_broadcaster:
type: joint_state_broadcaster/JointStateBroadcaster
forward_position_controller:
type: forward_command_controller/ForwardCommandController
......
......@@ -2,52 +2,50 @@ controller_manager:
ros__parameters:
update_rate: 2 # Hz
forward_command_controller_position:
type: forward_command_controller/ForwardCommandController
forward_position_controller:
type: position_controllers/JointGroupPositionController
forward_command_controller_velocity:
type: forward_command_controller/ForwardCommandController
forward_velocity_controller:
type: velocity_controllers/JointGroupVelocityController
forward_command_controller_acceleration:
forward_acceleration_controller:
type: forward_command_controller/ForwardCommandController
forward_command_controller_illegal1:
forward_illegal1_controller:
type: forward_command_controller/ForwardCommandController
forward_command_controller_illegal2:
forward_illegal2_controller:
type: forward_command_controller/ForwardCommandController
joint_state_broadcaster:
type: joint_state_broadcaster/JointStateBroadcaster
forward_command_controller_position:
forward_position_controller:
ros__parameters:
joints:
- joint1
- joint2
interface_name: position
forward_command_controller_velocity:
forward_velocity_controller:
ros__parameters:
joints:
- joint1
- joint2
interface_name: velocity
forward_command_controller_acceleration:
forward_acceleration_controller:
ros__parameters:
joints:
- joint1
- joint2
interface_name: acceleration
forward_command_controller_illegal1:
forward_illegal1_controller:
ros__parameters:
joints:
- joint1
interface_name: position
forward_command_controller_illegal2:
forward_illegal2_controller:
ros__parameters:
joints:
- joint2
......
# Copyright 2020 ros2_control Development Team
#
# 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.actions import DeclareLaunchArgument
from launch.substitutions import Command, FindExecutable, LaunchConfiguration, PathJoinSubstitution
from launch_ros.actions import Node
from launch_ros.substitutions import FindPackageShare
def generate_launch_description():
# Declare arguments
declared_arguments = []
declared_arguments.append(
DeclareLaunchArgument(
"runtime_config_package",
default_value="ros2_control_demo_bringup",
description='Package with the controller\'s configuration in "config" folder. \
Usually the argument is not set, it enables use of a custom setup.',
)
)
declared_arguments.append(
DeclareLaunchArgument(
"controllers_file",
default_value="diffbot_diff_drive_controller.yaml",
description="YAML file with the controllers configuration.",
)
)
declared_arguments.append(
DeclareLaunchArgument(
"description_package",
default_value="ros2_control_demo_description",
description="Description package with robot URDF/xacro files. Usually the argument \
is not set, it enables use of a custom description.",
)
)
declared_arguments.append(
DeclareLaunchArgument(
"description_file",
default_value="diffbot_system.urdf.xacro",
description="URDF/XACRO description file with the robot.",
)
)
declared_arguments.append(
DeclareLaunchArgument(
"prefix",
default_value='""',
description="Prefix of the joint names, useful for \
multi-robot setup. If changed than also joint names in the controllers' configuration \
have to be updated.",
)
)
declared_arguments.append(
DeclareLaunchArgument(
"use_sim",
default_value="false",
description="Start robot in Gazebo simulation.",
)
)
declared_arguments.append(
DeclareLaunchArgument(
"use_fake_hardware",
default_value="true",
description="Start robot with fake hardware mirroring command to its states.",
)
)
declared_arguments.append(
DeclareLaunchArgument(
"fake_sensor_commands",
default_value="false",
description="Enable fake command interfaces for sensors used for simple simulations. \
Used only if 'use_fake_hardware' parameter is true.",
)
)
declared_arguments.append(
DeclareLaunchArgument(
"robot_controller",
default_value="diffbot_base_controller",
description="Robot controller to start.",
)
)
# Initialize Arguments
runtime_config_package = LaunchConfiguration("runtime_config_package")
controllers_file = LaunchConfiguration("controllers_file")
description_package = LaunchConfiguration("description_package")
description_file = LaunchConfiguration("description_file")
prefix = LaunchConfiguration("prefix")
use_sim = LaunchConfiguration("use_sim")
use_fake_hardware = LaunchConfiguration("use_fake_hardware")
fake_sensor_commands = LaunchConfiguration("fake_sensor_commands")
robot_controller = LaunchConfiguration("robot_controller")
# Get URDF via xacro
robot_description_content = Command(
[
PathJoinSubstitution([FindExecutable(name="xacro")]),
" ",
PathJoinSubstitution(
[FindPackageShare(description_package), "urdf", description_file]
),
" ",
"prefix:=",
prefix,
" ",