[ roscon2022_control_workshop ](/ros-
controls/roscon2022_workshop/tree/master/roscon2022_control_workshop
"roscon2022_control_workshop")


_RRBot_ with GPIO interfaces.


1. ` export_state_interfaces ` / ` export_command_interfaces ` : report the state and command interfaces supported by this system class. These interfaces can then be checked by the controller for compatibility.


Task is to setup the XACRO for RRbot in a package called `
controlko_description ` .


[ Mike Likes Robots ](/@mikelikesrobots)


Next, to make things smoother in case we ever want to go back to the old one,
we’ll move the ` toxml() ` up to the process call. Hopefully you can see that
that won’t really change anything except that ` robot_description_config `
will now be the final string (rather than some ` xacro ` object), which makes
more sense anyway.


[ controlko_controllers ](/ros-
controls/roscon2022_workshop/tree/master/controlko_controllers
"controlko_controllers")


2. Test execution with ` forward_position_controller ` and ` joint_trajectory_controller `


##  Use saved searches to filter your results more quickly


Taking the steps below will let us easily swap between the Gazebo diff drive
plugin and the ros2_control one.


* How are statuses from controller published to ROS topics?


* Example 2: [ _DiffBot_ ](/ros-controls/ros2_control_demos/blob/master/example_2)


* Solutions


ros2_control uses a different method of communication from the standard ROS2
publish/subscribe messaging. Instead, the controller will load the code for
the motors as a **plugin library** , and directly call functions inside it.
This is the reason we had to rewrite the motor driver in C++ - it _has_ to be
a library that can be loaded by ros2_control, which is written in C++.


For


[ Sign in ](/login?return_to=https%3A%2F%2Fgithub.com%2Fros-
controls%2Fros2_control_demos)


##  Footer


References:


4. Create a launch file that starts ` ros2_controllers_test_nodes/publisher_joint_trajectory_controller ` to publish goals for the JTC.


Search or jump to...


[ ros2_control_demos.rolling.repos ](/ros-
controls/ros2_control_demos/blob/master/ros2_control_demos.rolling.repos
"ros2_control_demos.rolling.repos")


1
2
3
4


    # At the top
    from launch.substitutions import Command

    # Down where we were

    #robot_description_config = xacro.process_file(xacro_file).toxml()
    robot_description_config = Command(['xacro ', xacro_file, ' use_ros2_control:=', use_ros2_control])

---|---
`


    * [ Learning Pathways  ](https://resources.github.com/learn/pathways/)
    * [ White papers, Ebooks, Webinars  ](https://resources.github.com/)
    * [ Customer Stories ](/customer-stories)
    * [ Partners  ](https://partner.github.com/)


{{ message }}


  * [ https://wiki.ros.org/urdf ](https://wiki.ros.org/urdf)
  * [ https://wiki.ros.org/urdf/XML ](https://wiki.ros.org/urdf/XML)


1. ` ros2 launch controlko_bringup rrbot.launch.py `


###  License


If we rerun Gazebo now we’ll see that RViz is much smoother.


[ LICENSE ](/ros-controls/ros2_control_demos/blob/master/LICENSE "LICENSE")


Check updated files from the above list. To start the Gazebo Classic
simulation use:


###  Watchers


  * README
  * Apache-2.0 license


Go to file


Additional navigation options


1
2
3
4
5
6
7
8
9
10
11
12
13
14


    ros2 topic pub /forward_position_controller/commands std_msgs/msg/Float64MultiArray "
    layout:
     dim: []
     data_offset: 0
    data:
     - 0.7
     - 0.7"


Each joint then defines a number of command and state interfaces. Each command
interface accepts velocity, position, or effort commands, which allows
ros2_control controllers to command the joints to move as it needs. State
interfaces report a measurement from the joint out of velocity, position, or
effort, which allows ros2_control to monitor how much the joint has actually
moved and adjust itself. In our case, each joint accepts velocity commands and
reports measured velocity - although we configure the controller to ignore the
velocity, because we don't actually have a sensor like an encoder in the
JetBot. This means we're using **open loop** control, as opposed to **closed
loop** control.


[ example_14 ](/ros-controls/ros2_control_demos/tree/master/example_14
"example_14")


JetBot Description


Apache-2.0 license


[ Kubernetes  ](/kubernetes)


[ .clang-format ](/ros-controls/roscon2022_workshop/blob/master/.clang-format
".clang-format")


Uses repos file: ` src/$NAME$/$NAME$-not-released.<ros-distro>.repos `


**NOTE** : When running simulation be sure to set the joint limits defined in
the macro file.


    1
    2
    3


Explore


2. Create a launch file named ` rrbot.launch.py ` that starts the ros2_control node with the correct robot description.


[ example_2 ](/ros-controls/ros2_control_demos/tree/master/example_2
"example_2")


1. Create or adjust a package named ` controlko_hardware_interface ` with hardware interface files.


##  About


  * Package: ` gazebo_ros2_control `
  * Simulator plugin: ` libgazebo_ros2_control.so `
  * HW interface plugin: ` gazebo_ros2_control/GazeboSystem `


No releases published


  * [ Commonly used robot-package structure ](https://stoglrobotics.github.io/ros_team_workspace/master/guidelines/robot_package_structure.html)
  * [ Creating a new package ](https://stoglrobotics.github.io/ros_team_workspace/master/use-cases/ros_packages/create_package.html)
  * [ Setting up robot description ](https://stoglrobotics.github.io/ros_team_workspace/master/use-cases/ros_packages/setup_robot_description_package.html)


[ DevOps  ](/devops)


[ ros2_control_demos ](/ros-
controls/ros2_control_demos/tree/master/ros2_control_demos
"ros2_control_demos")


ros2_control Launch Execution


##  Explore  →


  * Set up xacro parameters for all the key dimensions and set them accordingly
  * Changed my Gazebo and RViz colours to match the real robot
  * Fixed up the controller YAML to have the correct wheel separation and radius
  * Added an extra xacro file for a smiley face on the front, like my real one currently has (it will eventually have a screen)


##  Details about the workshop


###  Pass in the Launch argument


    * [ Topics ](/topics)
    * [ Trending ](/trending)
    * [ Collections ](/collections)


Running on the JetBot


    gazebo:
      ros__parameters:
        publish_rate: 400.0

---|---
`


WaveShare JetBot AI Kit image edited from https://www.nvidia.com/en-
us/autonomous-machines/embedded
As the motor configuration is the same, the mathematics for controlling them
is also the same, which means we can write one controller to control either
robot - assuming we can abstract away the code to move the motors.


Query


2. During the implementation take care about the following details:


2. Semi-binary builds - against released core ROS packages (main and testing), but the immediate dependencies are pulled from source. Shows that local build with dependencies is possible and if fails there we can expect that after the next package sync we will not be able to build.


##  Update URDF to match robot structure


No description, website, or topics provided.


  * [ Commonly used robot-package structure ](https://stoglrobotics.github.io/ros_team_workspace/master/guidelines/robot_package_structure.html)
  * [ Creating a new package ](https://stoglrobotics.github.io/ros_team_workspace/master/use-cases/ros_packages/create_package.html)
  * [ Setup robot’s hardware package ](https://stoglrobotics.github.io/ros_team_workspace/master/use-cases/ros2_control/setup_robot_hardware_interface.html)


###  Footer navigation


Then in ` launch_sim.launch.py ` where we were including our robot state
publisher launch, we can set it to whatever we want by updating the `
launch_arguments ` line when including ` rsp.launch.py ` :


ros2 launch controlko_bringup rrbot_sim_gazebo.launch.py


We read every piece of feedback, and take your input very seriously.


3. Write a controller that uses ` control_msgs/msg/JointJog ` message for the input.


[ example_7 ](/ros-controls/ros2_control_demos/tree/master/example_7
"example_7")


ROS2 Control Demos Repository


  * [ __ ](https://www.youtube.com/c/ArticulatedRobotics)
  * [ __ ](https://www.facebook.com/ArticulatedRobotics/)
  * [ __ ](https://twitter.com/articulatedrobo/)
  * [ __ ](https://www.linkedin.com/company/articulated-robotics/)
  * [ __ ](https://github.com/joshnewans/)
  * [ Blog ](/index.html)
  * [ Community ](https://discourse.articulatedrobotics.xyz/)
  * [ About ](/about)
  * [ Support Us! ](/support)


* Example 13: "Multi-robot example (tba.)"


###  Add xacro argument & condition


**NOTE** \- The structure of packages, folders and files given in this
repository is not recommended to be used for your robot. Usually you should
have all of the above folders defined as separate packages with naming
convention ` <robot_name_or_type>/[bringup|description|hardware|controllers] `
. More standard structure can be found in [ ros_control_boilerplate
](https://github.com/PickNikRobotics/ros_control_boilerplate) repository from
Dave Coleman or documentation on [ ros_team_workspace
](https://rtw.stoglrobotics.de/master/guidelines/robot_package_structure.html)
from Stogl Robotics.


2. Write a hardware interface that uses a header-only library for the communication with _RRBot_ :


Turtlebot 3 Burger image edited from
https://www.robotis.us/turtlebot-3-burger-us/


Include my email address so I can be contacted


[ ros2_control_demos.humble.repos ](/ros-
controls/ros2_control_demos/blob/master/ros2_control_demos.humble.repos
"ros2_control_demos.humble.repos")


[ ](https://twitter.com/awsdevelopers)


Last commit date

---|---|---|---

##  Latest commit


The plugins and interfaces for the simulators are the following:


We then define the ros2_control portion with type ` system ` :


mkdir  ~/dev_ws
cd  ~/dev_ws
git  clone  https://github.com/mikelikesrobots/jetbot-ros-control -b jetbot-
motors-pt2
cp  -r ./jetbot-ros-control/.devcontainer .


Thank you for your interest in ros2_control. This repository was developed
with the purpose of supporting the workshop on _ros2_control_ @ ROSCon2022 in
Kyoto, Japan. Whether you participated or not, the repository will provide you
with detailed instructions on how to use the _ros2_control_ framework and
explain functionality and purpose of its individual parts.


[ Branches  ](/ros-controls/roscon2022_workshop/branches) [ Tags  ](/ros-
controls/roscon2022_workshop/tags)


Once running, you should be able to use the standard keyboard controls written
on screen to move the robot around. Cool!


_Mock Hardware_ is mocking ros2_control ` Hardware Interface ` based on the
robot's description from the ` ros2_control ` tag. Its purpose is to simplify
and boost the development process when creating a new controller or setting up
their configuration. The advantage of using it, over simulation or real
hardware, is a very fast start-up and lean functionality. It is a well tested
module helping you focus on other components in your setup knowing that your
"hardware" behaves ideally. _NOTE:_ the functionality of _Mock Hardware_ is
intentionally limited and it only enables you to reflect commanded values on
the state interfaces with the same name. Nevertheless, this is sufficient for
most tasks.


* [ Pricing ](/pricing)


[ Resilience  ](/resilience)


Lifecycle diagrams from the [ Task 6 ](/ros-
controls/roscon2022_workshop/blob/master) explains in detail when which method
is used.


> On my computer I also get an error printed in the Gazebo terminal which is a
> bit annoying, I think the Gazebo command line parser is treating the file as
> an extra SDF to load and failing. We can just ignore it, but if you’ve got a
> fix then let me know!


[ ](/ros-controls/ros2_control_demos/commits/master/)

###


Check the files listed above and execute:


< joint  name  =  "${prefix}left_wheel_joint"  >
< command_interface  name  =  "velocity"  />
< state_interface  name  =  "velocity"  />
</  joint  >


2. ` on_init ` / ` on_activate ` / ` on_deactivate ` : lifecycle methods automatically called by the controller. Different setup stages for the System occur in these methods, including enabling the motors in the ` on_activate ` method and stopping them in ` on_deactivate ` .


[ Dockerfile ](/ros-controls/ros2_control_demos/tree/master/Dockerfile
"Dockerfile")


##  RViz Config


Name  |  Name  |


[ README.md ](/ros-controls/roscon2022_workshop/blob/master/README.md
"README.md")


###  Forks


Write a hardware interface for the _RRBot_ .


##  History


then publish a command to the forward command controller:


    ros2 launch my_package launch_sim.launch.py use_ros2_control:=false

---|---
`


Toggle navigation


It’s difficult to describe in text (just watch the video) but essentially,
when using ros2_control with Gazebo the sensor output appears to be out of
sync with the published transforms.


For more details check [ this presentation
](https://control.ros.org/master/doc/resources/resources.html#ros-world-2021)


  1. ` ros2 control list_controllers `
  2. ` ros2 control list_controllers `
  3. ` ros2 service call /controller_manager/list_hardware_components controller_manager_msgs/srv/ListHardwareComponents {} `
  4. ` ros2 control list_hardware_interfaces `
  5. ` ros2 run controller_manager spawner forward_position_controller --inactive ` ` ros2 control switch_controllers --deactivate joint_trajectory_controller --activate forward_position_controller `
  6. See output in the terminal where ` ros2_control_node ` is running: ` ros2 control switch_controllers --activate joint_trajectory_controller `
  7. ` ros2 control list_controllers -v `


|

View all files

##  Repository files navigation


[ ros2_control_demos-not-released.rolling.repos ](/ros-
controls/ros2_control_demos/blob/master/ros2_control_demos-not-
released.rolling.repos "ros2_control_demos-not-released.rolling.repos")


#####  Solution:


  * [ Code  ](/ros-controls/roscon2022_workshop)
  * [ Issues  2  ](/ros-controls/roscon2022_workshop/issues)
  * [ Pull requests  0  ](/ros-controls/roscon2022_workshop/pulls)
  * [ Actions  ](/ros-controls/roscon2022_workshop/actions)
  * [ Projects  0  ](/ros-controls/roscon2022_workshop/projects)
  * [ Security  ](/ros-controls/roscon2022_workshop/security)
  * [ Insights  ](/ros-controls/roscon2022_workshop/pulse)


  * it abstracts hardware and low-level control for other frameworks such as MoveIt2 and Nav2;
  * it provides resource access management,
  * controls their lifecycle and so on.


[ Cost Optimization  ](/cost-optimization)


Closed loop control is far more accurate than open loop control. Imagine
you're trying to sprint exactly 100 metres from a starting line, but you have
to do it once blindfolded, and once again without a blindfold and line
markings every ten metres - which run is likely to be more accurate? In the
JetBot, there's no sensor to measure how much it has moved, so the robot is
effectively blindfolded and guessing how far it has travelled. This means our
navigation won't be as accurate - we are limited by hardware.


[ example_11 ](/ros-controls/ros2_control_demos/tree/master/example_11
"example_11")


This tells any controller loading our JetBot system hardware which pins are
used to drive the PWM chip. But, we're not done yet - we also need to tell
ros2_control the _command_ and _state_ interfaces available.


[ ros2_control_demos-not-released.humble.repos ](/ros-
controls/ros2_control_demos/blob/master/ros2_control_demos-not-
released.humble.repos "ros2_control_demos-not-released.humble.repos")


    1
    2
    3
    4
    5
    6


[ example_4 ](/ros-controls/ros2_control_demos/tree/master/example_4
"example_4")


  1. What and where is _Controller Manager_ ?
  2. What are _Controllers_ ? How they can be seen in ROS2?
  3. What is _Resource Manager_ ? Where can you see it? How to access it?
  4. What is _Hardware Interface_ ? Where is this stored? How to interact with it?


[ Star  ](/login?return_to=%2Fros-controls%2Fros2_control_demos)


###  Resources


  * [ C++  55.9%  ](/ros-controls/roscon2022_workshop/search?l=c%2B%2B)
  * [ Python  31.7%  ](/ros-controls/roscon2022_workshop/search?l=python)
  * [ CMake  7.9%  ](/ros-controls/roscon2022_workshop/search?l=cmake)
  * [ C  4.5%  ](/ros-controls/roscon2022_workshop/search?l=c)


###  Forks


    1. 🗒 Setting up the robot's URDF using XACRO
    2. 📝 Extending the robot's URDF with the ` <ros2_control> ` tag
  2. 🖥 Using the _Mock Hardware_ plugin for easy and generic testing of the setup (and how it can save you ton of time and nerves)


Using xacro to build our URDF gives us the ability to pass in an argument at
runtime to change the result. This could be anything like the length of an
arm, the colour of a wheel, but in this case we want to pass in a boolean to
tell it whether to use ros2_control or not.


[ .gitignore ](/ros-controls/ros2_control_demos/blob/master/.gitignore
".gitignore")


7. 🤖 How to write a hardware interface for a robot


[ ](https://www.youtube.com/channel/UCT-nPlVzJI-ccQXlxjSvJmw)


4. An overall description file that imports the ros2_control file and calls the macro


* [ GitHub Sponsors  Fund open source developers  ](/sponsors)


###  1\. 📑 Setting up the hardware description for _ros2_control_


* Example 1: [ _RRBot_ ](/ros-controls/ros2_control_demos/blob/master/example_1)


[ example_7 ](/ros-controls/ros2_control_demos/tree/master/example_7
"example_7")


Kinematics:


3. Check that the provided hardware information matches the expected information - for example, that there are two velocity command interfaces


[ doc ](/ros-controls/ros2_control_demos/tree/master/doc "doc")


[ « Making a Mobile Robot #12 - ros2_control Concept & Simulation
](https://articulatedrobotics.xyz/mobile-robot-12-ros2-control/) [ Making a
Mobile Robot #13 - Using ros2_control on a real robot »
](https://articulatedrobotics.xyz/mobile-robot-13-ros2-control-real/)


    * check the file ` controlko_hardware_interface/include/controlko_hardware_interface/dr_denis_rrbot_comms.hpp `
    * use [ Writing a new hardware interface manual ](https://control.ros.org/master/doc/ros2_control/hardware_interface/doc/writing_new_hardware_interface.html) to implement everything needed.
    * extend the URDF file to use hardware interface
  3. During the implementation of the hardware interface take care about the following details:


This post shows how to perform this process for the JetBot. We're going to use
the I2C and motor classes from the [ previous post in the series
](http://localhost:3000/blog/jetbot-motors-pt2) to define a ros2_control
system that will work with the differential drive controller. We use a System
rather than an Actuator because we want to define one class that can control
both motors in one ` write ` call, instead of having two separate Actuators.


Featured Spaces


#####  Task


controls/ros2_control_demos/actions/workflows/humble-semi-binary-
build.yml?branch=humble)
|  [ Documentation ](https://control.ros.org/humble/index.html)
[ API Reference ](https://control.ros.org/humble/doc/api/index.html)

###  Explanation of different build types


Resources


Go to file


    gazebo_params_path = os.path.join(
                      get_package_share_directory(package_name),'config','gazebo_params.yaml')

    gazebo = IncludeLaunchDescription(
                PythonLaunchDescriptionSource([os.path.join(
                    get_package_share_directory('gazebo_ros'), 'launch', 'gazebo.launch.py')]),
                    launch_arguments={'extra_gazebo_args': '--ros-args --params-file ' + gazebo_params_path }.items()
             )

---|---
`


3. Test forward command controller by sending a reference to it using ` ros2 topic pub ` command.


[ .pre-commit-config.yaml ](/ros-controls/ros2_control_demos/blob/master/.pre-
commit-config.yaml ".pre-commit-config.yaml")


This _should_ be straightforward but actually isn’t. Right now this file is
using the ` xacro ` Python module to process the file, which is all well and
good, and it has the option ( _don’t type this!_ ) to set arguments by
specifying the mappings like so:


Share


#  Building a ros2_control System: ROS2 Control with the JetBot Part 2


Branch: ` 8-write-controller/task `


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


**TIPP** :


So, if ` use_ros2_control ` is true, include the ` ros2_control.xacro ` file,
and unless ` use_ros2_control ` is true, include ` gazebo_control.xacro ` .


###  Installing this repository


  1. What controllers are loaded in the system?
  2. What is the state of the controllers?
  3. What hardware interfaces are there and in which state?
  4. Which interfaces are available?
  5. How can we switch between ` forward_position_controller ` and ` joint_trajectory_controller ` ?
  6. What happens when you try to run all controllers in parallel?
  7. What interfaces are controllers using?


Execute the following commands to get the answers from the task:


// 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.
#ifndef HARDWARE_INTERFACE__COMPONENT_PARSER_HPP_
#define HARDWARE_INTERFACE__COMPONENT_PARSER_HPP_
#include <string>
#include <unordered_map>
#include <vector>
#include "hardware_interface/hardware_info.hpp"
#include "hardware_interface/visibility_control.h"
namespace hardware_interface
{
/// Search XML snippet from URDF for information about a control component.
/**
 * \param[in] urdf string with robot's URDF
 * \return vector filled with information about robot's control resources
 * \throws std::runtime_error if a robot attribute or tag is not found
 */
HARDWARE_INTERFACE_PUBLIC
std::vector<HardwareInfo> parse_control_resources_from_urdf(const std::string & urdf);
}  // namespace hardware_interface
#endif  // HARDWARE_INTERFACE__COMPONENT_PARSER_HPP_


This repository provides examples for functionalities and capabilities of `
ros2_control ` framework. It consists of simple implementations that
demonstrate different concepts. Choose the right branch of this repository
matching you ROS 2 distribution as well as the full documentation on [
control.ros.org ](https://control.ros.org) , see  this table  .


We read every piece of feedback, and take your input very seriously.


* [ ros ](/categories#ros)


_RRBot_ with an externally connected sensor.


[ ](/ros-controls/roscon2022_workshop/commits/master/)

###


In the private fields of the class, we create the fields that we will need
during execution. This includes the ` I2CDevice ` and two ` Motor ` classes
from the [ previous post ](http://localhost:3000/blog/jetbot-motors-pt1) ,
along with two vectors for the hardware commands and hardware velocities:


[ Apache-2.0 license ](/ros-controls/ros2_control_demos/blob/master/LICENSE)


_RRBot_ \- or ''Revolute-Revolute Manipulator Robot'' - a simple position
controlled robot with one hardware interface. This example also demonstrates
the switching between different controllers.


###  Pass in the xacro argument


< xacro:include  filename  =  "$(find
jetbot_control)/ros2_control/jetbot.ros2_control.xacro"  />
< xacro:jetbot_ros2_control
name  =  "JetBot"  prefix  =  "$(arg prefix)"  use_mock_hardware  =  "$(arg
use_mock_hardware)"  />


[ example_10 ](/ros-controls/ros2_control_demos/tree/master/example_10
"example_10")


Next Steps


Then, a number of methods need to be overridden from the base class. Take a
look at the [ full header file ](https://github.com/mikelikesrobots/jetbot-
ros-control/blob/jetbot-motors-
pt2/hardware/include/jetbot_control/jetbot_system.hpp) to see them, but
essentially it boils down to three concepts:


[ LICENSE ](/ros-controls/roscon2022_workshop/blob/master/LICENSE "LICENSE")


[ controlko_hardware_interface ](/ros-
controls/roscon2022_workshop/tree/master/controlko_hardware_interface
"controlko_hardware_interface")


< ros2_control  name  =  "${name}"  type  =  "system"  >


#####  🛠 How to setup _Mock Hardware_ for a robot?


Resources


    * [ Learning Pathways  ](https://resources.github.com/learn/pathways/)
    * [ White papers, Ebooks, Webinars  ](https://resources.github.com/)
    * [ Customer Stories ](/customer-stories)
    * [ Partners  ](https://partner.github.com/)


##  Problem 3 - Sensor synchronisation issue


[ ros2_control_demos.rolling.repos ](/ros-
controls/ros2_control_demos/blob/master/ros2_control_demos.rolling.repos
"ros2_control_demos.rolling.repos")


* Example 5: [ "Industrial robots with externally connected sensor" ](/ros-controls/ros2_control_demos/blob/master/example_5)


    xacro.process_file(xacro_file, mappings={'use_ros2_control': 'true'})

---|---
`


* Example 10: [ "Industrial robot with GPIO interfaces" ](/ros-controls/ros2_control_demos/blob/master/example_10)


[ controlko_description ](/ros-
controls/roscon2022_workshop/tree/master/controlko_description
"controlko_description")


Then use the Dev Containers plugin to rebuild and reload the container. This
will take a few minutes, but the step is crucial to allow us to run ROS2
Humble on the JetBot, which uses an older version of Ubuntu. Once complete, we
can build the workspace, source it, and launch the controller:


[ .clang-format ](/ros-controls/ros2_control_demos/blob/master/.clang-format
".clang-format")


  * [ Code  ](/ros-controls/ros2_control_demos)
  * [ Issues  ](/ros-controls/ros2_control_demos/issues)
  * [ Pull requests  ](/ros-controls/ros2_control_demos/pulls)
  * [ Actions  ](/ros-controls/ros2_control_demos/actions)
  * [ Projects  ](/ros-controls/ros2_control_demos/projects)
  * [ Security  ](/ros-controls/ros2_control_demos/security)
  * [ Insights  ](/ros-controls/ros2_control_demos/pulse)


We’ll start by adding an argument declaration at the start of our `
robot.urdf.xacro ` , and default it to true (we generally do want to use
ros2_control).


[ Report repository ](/contact/report-
content?content_url=https%3A%2F%2Fgithub.com%2Fros-
controls%2Froscon2022_workshop&report=ros-controls+%28user%29)


  1. Start the ` RRbot ` with ` Mock System `
  2. Check the lifecycle state of controllers and hardware interfaces
  3. Activate the ` joint_trajectory_controller ` controller. What else do you have to do to achieve that?
  4. Set hardware to ` inactive ` state. What is now the internal state of the _ros2_control_ instance?
  5. Have you heard of the ` RQT Controller Manager ` plugin? Try it!


Branch: ` 6-getting-know-lifecycle `


[ ](https://github.com "GitHub") © 2024 GitHub, Inc.


We will be using [ example 2 ](https://github.com/ros-
controls/ros2_control_demos/tree/master/example_2) from this demo repository
as a basis, but stripping out anything we don't require right now, like
supporting simulation; we can return these parts in later iterations as we
come to understand them.


[ Sign in ](/login?return_to=https%3A%2F%2Fgithub.com%2Fros-
controls%2Froscon2022_workshop)


* Product


Now execute the test script for joint trajectory controller to move the robot.


  * Force Torque Sensor at TCP (6D)
  * 2 digital inputs and output (outputs can be measured)


**NOTE** : delay between spawning controllers is usually not necessary, but
useful when starting a complex setup. Adjust this specifically for the
specific use-case.


You can check out the differences [ here
](https://github.com/joshnewans/articubot_one/commit/11b64ef21fa61da4d99e5aa0a11163596db7f569)
.


_RRBot_ with an integrated sensor.


Now when we use ` xacro ` to build the overall description file, it will
import the ros2_control file macro and expand it, giving a complete robot
description that we can add to later. It's now time to look at creating a
controller manager and a differential drive controller.


master


* Example 8: [ "Using transmissions" ](/ros-controls/ros2_control_demos/blob/master/example_8)


We now need Gazebo to see these parameters when it starts up. In our `
launch_sim.launch.py ` we are “including” the ROS-provided Gazebo launch. This
launch file has an argument called ` extra_gazebo_args ` which lets us just
send whatever we want down to the Gazebo it runs. In this case, we’ll create a
variable to store the path of our params file (similar to how we handled the
URDF), and then combine that path into a string telling Gazebo to read it.


_DiffBot_ , or ''Differential Mobile Robot'', is a simple mobile base with
differential drive. The robot is basically a box moving according to
differential drive kinematics.


    ## Was
    robot_description_config = xacro.process_file(xacro_file)
    params = {'robot_description': robot_description_config.toxml(), 'use_sim_time': use_sim_time}

    ## Now
    robot_description_config = xacro.process_file(xacro_file).toxml()
    params = {'robot_description': robot_description_config, 'use_sim_time': use_sim_time}

---|---
`


To start ` RRBot ` with JTC execute:


We’ll go ahead and make the launch argument anyway, right under our `
use_sim_time ` one.


  * [ Code  ](/ros-controls/ros2_control_demos)
  * [ Issues  19  ](/ros-controls/ros2_control_demos/issues)
  * [ Pull requests  4  ](/ros-controls/ros2_control_demos/pulls)
  * [ Actions  ](/ros-controls/ros2_control_demos/actions)
  * [ Projects  0  ](/ros-controls/ros2_control_demos/projects)
  * [ Security  ](/ros-controls/ros2_control_demos/security)
  * [ Insights  ](/ros-controls/ros2_control_demos/pulse)


[ .clang-format ](/ros-controls/roscon2022_workshop/blob/master/.clang-format
".clang-format")


* Example 12: [ "Controller chaining" ](/ros-controls/ros2_control_demos/blob/master/example_12)


source  /opt/ros/humble/setup.bash
colcon build --symlink-install
source  install/setup.bash
ros2 launch jetbot_control jetbot.launch.py


Copyright © 2023 Articulated Robotics


#####  GOAL


#  Saved searches


[ Custom properties  ](/ros-controls/ros2_control_demos/custom-properties)


Check the files listed above and execute:


#  Provide feedback


1. A plugin library capable of writing commands to the JetBot motors


[ .github ](/ros-controls/ros2_control_demos/tree/master/.github ".github")


##  [ Contributors  4  ](/ros-
controls/roscon2022_workshop/graphs/contributors)


Let's do one more experiment, to see how the configuration works. Go into the
` jetbot_controllers.yaml ` file and play with the maximum velocity and
acceleration fields, to see how the robot reacts. Relaunch after every
configuration change to see the result. You can also tune these parameters to
match what you expect more closely.


###  Topics


Additionally, if you are still having issues with wheels skidding and drifting
oddly, try experimenting with the friction parameters like we did for the
caster.


![JetBot image with arrows noting wheels and
caster](https://assets.community.aws/a/2dkAMR4tUTmJ1M7I28ySU5cDQ3n/jetbo.webp)


  * [ Code  ](/ros-controls/roscon2022_workshop)
  * [ Issues  ](/ros-controls/roscon2022_workshop/issues)
  * [ Pull requests  ](/ros-controls/roscon2022_workshop/pulls)
  * [ Actions  ](/ros-controls/roscon2022_workshop/actions)
  * [ Projects  ](/ros-controls/roscon2022_workshop/projects)
  * [ Security  ](/ros-controls/roscon2022_workshop/security)
  * [ Insights  ](/ros-controls/roscon2022_workshop/pulse)


1
2
3
4
5
6
7


This should launch the controller and allow it to connect to the motors
successfully. Now we can use ` teleop_twist_keyboard ` to test it - but with a
couple of changes.


Repositories


  * Update URDF to match robot structure
  * Problem 1 - Gazebo clock rate
  * Problem 2 - Wheel drift
  * Problem 3 - Sensor synchronisation issue
  * Swapping between control methods
    * Add xacro argument & condition
    * Pass in the xacro argument
    * Pass in the Launch argument
  * RViz Config
  * Conclusion


[ ](https://github.com/)


[ CONTRIBUTING.md ](/ros-
controls/ros2_control_demos/blob/master/CONTRIBUTING.md "CONTRIBUTING.md")


1. Setup the following controllers for the ` RRBot ` :


    * [ Actions  Automate any workflow  ](/features/actions)
    * [ Packages  Host and manage packages  ](/features/packages)
    * [ Security  Find and fix vulnerabilities  ](/features/security)
    * [ Codespaces  Instant dev environments  ](/features/codespaces)
    * [ Copilot  Write better code with AI  ](/features/copilot)
    * [ Code review  Manage code changes  ](/features/code-review)
    * [ Issues  Plan and track work  ](/features/issues)
    * [ Discussions  Collaborate outside of code  ](/features/discussions)


[ controlko_bringup ](/ros-
controls/roscon2022_workshop/tree/master/controlko_bringup
"controlko_bringup")


  * [ Terms ](https://docs.github.com/site-policy/github-terms/github-terms-of-service)
  * [ Privacy ](https://docs.github.com/site-policy/privacy-policies/github-privacy-statement)
  * [ Security ](/security)
  * [ Status ](https://www.githubstatus.com/)
  * [ Docs ](https://docs.github.com/)
  * [ Contact ](https://support.github.com?tags=dotcom-footer)
  * Manage cookies
  * Do not share my personal information


There are two options to interact with the ros2_control, first, using the CLI
interface with commands like ` ros2 control <command> ` (package `
ros2controlcli ` ), and second, using services from the controller manager
directly.


ros2 launch controlko_bringup test_joint_trajectory_controller.launch.py


[ ros2_control_demos-not-released.iron.repos ](/ros-
controls/ros2_control_demos/blob/master/ros2_control_demos-not-
released.iron.repos "ros2_control_demos-not-released.iron.repos")


Try to figure out how to answer the following questions using those tools:


[ ](https://www.instagram.com/awsdevelopers/)


[ LICENSE ](/ros-controls/roscon2022_workshop/blob/master/LICENSE "LICENSE")


Files to create or adjust:


**Hooray!** We have defined everything we need to launch ros2_control and
configure it to control our JetBot! Now we have a controller that is able to
move our robot around.


To help us with our ros2_control system implementation, the ros2_control
framework has helpfully provided us with a [ set of examples
](https://control.ros.org/master/doc/ros2_control_demos/doc/index.html) . One
of these examples is exactly what we want - building a differential drive
robot (or diffbot, in the examples) with a custom System for driving the
motors.


    * [ Topics ](/topics)
    * [ Trending ](/trending)
    * [ Collections ](/collections)


[ Sign in ](/login?return_to=https%3A%2F%2Fgithub.com%2Fros-
controls%2Froscon2022_workshop)


This article has been written from the bottom up, but now we have the full
story, we can look from the top down:


[ Branches  ](/ros-controls/ros2_control_demos/branches) [ Tags  ](/ros-
controls/ros2_control_demos/tags)


  * 2 DoF
  * 1st joint is on a pedestal (box 30x30x30 cm) 30 cm above the ground and rotates around the axis orthogonal to the ground
  * 1st link is 50cm long (cylinder with 20cm diameter)
  * 2nd joint is rotation orthogonal to the first link's height
  * 2nd link is 60cm long (10x10cm cross-section 5x5cm)


##  Build status


A full tutorial for a 6 DOF robot for intermediate ROS 2 users.


[ roscon2022_control_workshop ](/ros-
controls/roscon2022_workshop/tree/master/roscon2022_control_workshop
"roscon2022_control_workshop")


add_library(${PROJECT_NAME}
SHARED
hardware/src/jetbot_system.cpp
hardware/src/i2c_device.cpp
hardware/src/motor.cpp
)

...

pluginlib_export_plugin_description_file(hardware_interface
jetbot_control.xml)


[ Star  ](/login?return_to=%2Fros-controls%2Froscon2022_workshop)


[ Training and Certification  ](/training)


[ Search syntax tips ](https://docs.github.com/search-github/github-code-
search/understanding-github-code-search-syntax)


3. The launch file requests that the controller manager launches the differential drive controller


**Gazebo**


Previously, we wrote an example node that span the wheels using the motor
driver; now we are replacing this **executable** by a **library** that can be
loaded by ros2_control. In CMakeLists.txt, we can see:


Community Programs


##  Folders and files


[ TODOs.md ](/ros-controls/roscon2022_workshop/blob/master/TODOs.md
"TODOs.md")


There may be better methods than this - if you have one please let me know!


This is the second part of the "ROS2 Control with the JetBot" series, where I
show you how to get a JetBot working with ROS2 Control! This is a sequel to
the [ part 1 blog post ](http://localhost:3000/blog/jetbot-motors-pt2) , where
I showed how to drive the JetBot's motors using I2C and PWM with code written
in C++.


Last commit message


1
2


    ...
    launch_arguments={'use_sim_time': 'true', 'use_ros2_control': 'true'}.items()
    ...

---|---
`


Demonstrates how to switch between simulation and hardware.


    1
    2
    3
    4
    5
    6
    7
    8


There could be a few factors affecting this, but an easy one to tackle is that
the wheel collision is a cylinder, which means there will be subtle skidding
effects occuring due to the ground connection being a line. We could somewhat
alleviate this by reducing the thickness of the wheel collision cylinder, but
better is to reduce it infinitely, by replacing the cylinder with a sphere.
Now the contact with the ground will be a single point per wheel.


[ example_6 ](/ros-controls/ros2_control_demos/tree/master/example_6
"example_6")


ros2_control Joints, Command Interfaces, and State Interfaces


[ ros2_control_demos-not-released.iron.repos ](/ros-
controls/ros2_control_demos/blob/master/ros2_control_demos-not-
released.iron.repos "ros2_control_demos-not-released.iron.repos")


To see all available qualifiers, see our [ documentation
](https://docs.github.com/search-github/github-code-search/understanding-
github-code-search-syntax) .


[ example_14 ](/ros-controls/ros2_control_demos/tree/master/example_14
"example_14")


    1
    2
    3
    4
    5
    6


1
2
3
4
5
6
7
8
9


Cancel  Submit feedback


Code


1. Binary builds - against released packages (main and testing) in ROS distributions. Shows that direct local build is possible.


[ LICENSE ](/ros-controls/ros2_control_demos/blob/master/LICENSE "LICENSE")


  * [ Notifications ](/login?return_to=%2Fros-controls%2Fros2_control_demos)
  * [ Fork  165  ](/login?return_to=%2Fros-controls%2Fros2_control_demos)
  * [ Star  329  ](/login?return_to=%2Fros-controls%2Fros2_control_demos)


#  Saved searches


Let's summarize what we've created so far:


We start with the controller_manager. This is used to load one or more
controllers and swap between them. It also makes sure that resources are only
used by one controller at a time and manages the change between controllers.
In our case, we're only using it to load and run one controller:


If you want to have rather step by step manual how to do things with `
ros2_control ` checkout the [ ros-control/roscon2022_workshop
](https://github.com/ros-controls/roscon2022_workshop) repository.


[ AWS User Groups
](https://aws.amazon.com/developer/community/usergroups/?intClick=dev-
center-2021_main)


[ roscon2022_workshop.humble.repos ](/ros-
controls/roscon2022_workshop/blob/master/roscon2022_workshop.humble.repos
"roscon2022_workshop.humble.repos")


ros2 launch controlko_bringup rrbot.launch.py


[ AWS Community Builders
](https://aws.amazon.com/developer/community/community-builders/?intClick=dev-
center-2021_main)


2. The launch file spawns the **controller manager** , which is used to load controllers and manage resources


[ README.md ](/ros-controls/ros2_control_demos/blob/master/README.md
"README.md")


[ Apache-2.0 license ](/ros-controls/roscon2022_workshop/blob/master/LICENSE)


Clear


[ example_10 ](/ros-controls/ros2_control_demos/tree/master/example_10
"example_10")


First check the code:


##  [ Releases ](/ros-controls/roscon2022_workshop/releases)


ros2 launch controlko_bringup rrbot_sim_gazebo_classic.launch.py


Last commit message


#####  Solution:


You can’t perform that action at this time.


If we relaunch it we should see that a full rotation places us back where we
started.


The workaround is a little hacky but it’s not too bad, especially considering
launch scripts aren’t designed to be super python-heavy anyway. Instead of
using the xacro Python module we’re going to call the xacro process using the
launch ` Command ` substitution.


[ **165** forks ](/ros-controls/ros2_control_demos/forks)


controller_manager:
ros__parameters:
update_rate:  10  # Hz

jetbot_base_controller:
type:  diff_drive_controller/DiffDriveController


These will have the same effect, but the latter is a bit more explicit. We
should also remember to add an appropriate ` DeclareLaunchArgument ` entry.


    1
    2
    3
    4
    5
    6
    7


* Open Source


The following examples are part of this demo repository:


Let's define those plugins for ` RRBot ` :


* [ The ReadME Project  GitHub community articles  ](/readme)


All that remains is to build the package and launch the new launch file!


  * ` Joint State Broadcaster ` \- always needed to get ` /joint_states ` topic from a hardware.
  * ` Forward Command Controller ` \- sending position commands for the joints.
  * ` Joint Trajectory Controller ` \- interpolating trajectory between the position commands for the joint.


ros2 launch controlko_bringup rrbot.launch.py robot_controller:=joint_trajectory_controller


  * README
  * Apache-2.0 license


> Note that [ future versions ](https://github.com/ros-
> simulation/gazebo_ros_pkgs/pull/1391) should let us pass the params file in
> directly as a launch argument, simplifying this process ever so slightly.


Code Deep Dive


##  Problem 2 - Wheel drift


[ TODOs.md ](/ros-controls/roscon2022_workshop/blob/master/TODOs.md
"TODOs.md")


Cancel  Create saved search


[ Livestreams  ](/livestreams)


[ ros2_control_demos.iron.repos ](/ros-
controls/ros2_control_demos/blob/master/ros2_control_demos.iron.repos
"ros2_control_demos.iron.repos")


This repository aims at providing examples to illustrate ros2_control and
ros2_controllers


Branch: ` 2-robot-mock-hardware `


This is what I demonstrated in the video, however it would be nice to be able
to toggle it at runtime, i.e. by running:


So far, we've defined a JetBot using description files. Now we want to be able
to launch ros2_control and tell it what controller to create, how to configure
it, and how load our defined JetBot. For this, we use the `
jetbot_controllers.yaml ` file.


[ ](https://www.linkedin.com/showcase/aws-developers/)


[ **9** watching ](/ros-controls/roscon2022_workshop/watchers)


[ .pre-commit-config.yaml ](/ros-controls/ros2_control_demos/blob/master/.pre-
commit-config.yaml ".pre-commit-config.yaml")


Stay tuned for more posts in this series, where we will explore one or both of
these options, now that we have the robot integrated into ROS2 using
ros2_control.


Finally, we supply the wheel separation and radius, specified in metres. I
measured these from my own robot. The separation is the minimum separation
between wheels, and the radius is from the centre of one wheel to the very
edge:


**TIPP** : ` RosTeamWS ` tool has some scripts that can help you to solve this
task faster. Resources:


#  Search code, repositories, users, issues, pull requests...


This leaves the System initialized, but not yet activated. Once ` on_activate
` is called, the motors are enabled and ready to receive commands. The ` read
` and ` write ` methods are then repeatedly called for reading from and
writing to the motors respectively. When it's time to shutdown, `
on_deactivate ` will stop the motors, and the destructors of the classes
perform any required cleanup. There are more lifecycle states that could
potentially be used for a more complex system - these are documented in the [
ros2 demos repository
](https://github.com/ros2/demos/blob/humble/lifecycle/README.rst) .


    1
    2
    3
    4
    5
    6
    7


[ README.md ](/ros-controls/roscon2022_workshop/blob/master/README.md
"README.md")


The repository has a great many examples available. If you're here to learn
about ros2_control, but not to build a diffbot, there are examples of building
simulations, building URDF files representing robots, externally connected
sensors, and many more.


##  Structure of this repository (and workshop)


[ ML  ](/@mikelikesrobots)


[ 18 Commits  ](/ros-controls/roscon2022_workshop/commits/master/)


In fact, this is exactly what's provided by the [ ros2_controllers
](https://control.ros.org/master/doc/ros2_controllers/doc/controllers_index.html)
library. This library contains several standard controllers, including our
differential drive controller. We could build a JetBot and a Turtlebot by
setting up this standard controller to be able to move their motors - all we
need to do is write the code for moving the motors when commanded to by the
controller.


Name


These numbers are obtained through experimentation! ros2_control operates
using target velocities specified in radians per second [ [ source
](https://answers.ros.org/question/242766/what-is-the-unit-of-the-commands-
from-the-diff_drive_controller/) ]. However, the velocity we send to motors
doesn't correspond to radians per second - the range of -1 to +1 is the
minimum velocity up to maximum velocity of the motors, which change with the
battery level of the robot. I obtained the numbers given through
experimentation - these move the robot at a reasonable pace.


* Controller should have a _slow mode_ where displacements are reduced to half.


[ example_8 ](/ros-controls/ros2_control_demos/tree/master/example_8
"example_8")


##  Structure


[ example_5 ](/ros-controls/ros2_control_demos/tree/master/example_5
"example_5")


1. ` ros2 launch controlko_bringup rrbot.launch.py `


[ ros-controls ](/ros-controls) /  **[ ros2_control_demos ](/ros-
controls/ros2_control_demos) ** Public


  * learn how to setup the URDF of a robot using XACRO macros
  * learn what URDF changes are needed to integrate a robot with ` ros2_control `


[ **16** watching ](/ros-controls/ros2_control_demos/watchers)


< xacro:macro  name  =  "jetbot_ros2_control"  params  =  "name prefix
use_mock_hardware"  >


Fixing the clock rate is a bit annoying. First we need to create another
parameter file, a good name is ` gazebo_params.yaml ` . In it we’ll put the
following code, which is telling ` gazebo ` to publish the clock at 400Hz
instead of 10Hz (if your computer is slow you may need to reduce this).


##  About


##  [ Packages  0  ](/orgs/ros-
controls/packages?repo_name=roscon2022_workshop)


8. 🛂 How to write a controller


[ Student Communities  ](/students)


[ ](https://github.com "GitHub") © 2024 GitHub, Inc.


[ .gitignore ](/ros-controls/ros2_control_demos/blob/master/.gitignore
".gitignore")


Last commit date

---|---|---|---

##  Latest commit


There are actually two ways to achieve this. The first is to…do nothing. If we
**undo** the previous step where we passed down the launch argument, we’ll
find that we are able to set it at the command line and it will automatically
find its way down to where it needs to be.


###  5\. 💻 Simulating your hardware using Gazebo Classic and Gazebo


_There are a few follow-up points regarding ros2_control for our differential
drive robot that are worth sorting out before we move ahead with the rest of
the tutorial series. I’ve kept these out of the main video to avoid further
detracting from the core explanation of how to get ros2_control up and
running._


#  ros2_control Demos


Query


Include my email address so I can be contacted


ros2_control's purpose is to simplify integrating new hardware into ROS2. The
central idea is to separate controllers from [ systems, actuators, and sensors
](https://control.ros.org/master/doc/getting_started/getting_started.html#hardware-
components) . A controller is responsible for controlling the movement of a
robot; an actuator is responsible for moving a particular joint, like a motor
moving a wheel. There's a good reason for this separation: it allows us to
write a controller for a wheel configuration, without knowing which specific
motors are used to move the wheels.


[ transformations (5) ](/categories#transformations) [ linear (1)
](/categories#linear) [ coordinate (4) ](/categories#coordinate) [ 2d (1)
](/categories#2d) [ transforms (1) ](/categories#transforms) [ rotations (1)
](/categories#rotations) [ posts (1) ](/categories#posts) [ ros (23)
](/categories#ros)


[ example_12 ](/ros-controls/ros2_control_demos/tree/master/example_12
"example_12")


[ 251 Commits  ](/ros-controls/ros2_control_demos/commits/master/)


###  6\. 🔃 Getting familiar with the lifecycle of controllers and hardware and
how to use it


Also there are few graphical tools available for ` ros2_control ` : `
rqt_controller_manager ` and ` rqt_joint_trajectory_controller ` . Try to use
those tools.


Components are libraries, not nodes


##  Conclusion


[ ![ros2_control Overview](https://github.com/ros-
controls/control.ros.org/raw/master/doc/resources/images/ros2_control_overview.png)
](https://github.com/ros-
controls/control.ros.org/blob/master/doc/resources/images/ros2_control_overview.png)


|

View all files

##  Repository files navigation


1
2
3
4


Follow the steps provided in the [ documentation
](https://control.ros.org/master/doc/ros2_control_demos/doc/index.html#installation)
to install ros2_control_demos.


Branch: ` 7-robot-hardware-interface/solution `


Cancel  Create saved search


  3. Test activation of an incompatible controller using:

        ros2 control load_controller incompatible_joint_trajectory_controller
    ros2 control set_controller_state incompatible_joint_trajectory_controller inactive
    ros2 control switch_controllers --deactivate forward_position_controller --activate incompatible_joint_trajectory_controller


1
2
3
4
5
6


1. Add controller files into the ` controlko_controllers ` package.


    * [ Enterprise ](/enterprise)
    * [ Teams ](/team)
    * [ Startups ](/enterprise/startups)
    * [ Education  ](https://education.github.com)


< hardware  >
< plugin  > jetbot_control/JetBotSystemHardware  </  plugin  >
< param  name  =  "pin_enable_0"  > 8  </  param  >
< param  name  =  "pin_pos_0"  > 9  </  param  >
< param  name  =  "pin_neg_0"  > 10  </  param  >
< param  name  =  "pin_enable_1"  > 13  </  param  >
< param  name  =  "pin_pos_1"  > 12  </  param  >
< param  name  =  "pin_neg_1"  > 11  </  param  >
</  hardware  >


###  7\. 🤖 How to write a hardware interface for a robot


##  See how to build a ros2_control System with the Motor and I2CDevice
classes from the previous post, and how to integrate this System with a
Differential Drive Controller from ROS2.


Search or jump to...


###  Footer navigation


[ .clang-format ](/ros-controls/ros2_control_demos/blob/master/.clang-format
".clang-format")


[ ![Articulated Robotics](/assets/images/logo3.png) ](/)


ros2 launch controlko_bringup test_joint_trajectory_controller.launch.py


#####  Solution:


In this section, I'll take you through the key parts of my JetBot System
implementation for ros2_control. The code is available on [ Github
](https://github.com/mikelikesrobots/jetbot-ros-control/tree/jetbot-motors-
pt2) \- remember that this repository will be updated over time, so select the
tag ` jetbot-motors-pt2 ` to get the same code version as in this article!


##  Swapping between control methods


ROS 2 Distro  |  Branch  |  Build status  |  Documentation
---|---|---|---
**Rolling** |  [ ` master ` ](https://github.com/ros-
controls/ros2_control_demos/tree/rolling) |  [ ![Rolling Binary
Build](https://github.com/ros-
controls/ros2_control_demos/actions/workflows/rolling-binary-
build.yml/badge.svg?branch=master) ](https://github.com/ros-
controls/ros2_control_demos/actions/workflows/rolling-binary-
build.yml?branch=master)
[ ![Rolling Semi-Binary Build](https://github.com/ros-
controls/ros2_control_demos/actions/workflows/rolling-semi-binary-
build.yml/badge.svg?branch=master) ](https://github.com/ros-
controls/ros2_control_demos/actions/workflows/rolling-semi-binary-
build.yml?branch=master)
|  [ 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/ros2_control_demos/tree/iron) |  [ ![Iron Binary
Build](https://github.com/ros-
controls/ros2_control_demos/actions/workflows/iron-binary-
build.yml/badge.svg?branch=iron) ](https://github.com/ros-
controls/ros2_control_demos/actions/workflows/iron-binary-
build.yml?branch=iron)
[ ![Iron Semi-Binary Build](https://github.com/ros-
controls/ros2_control_demos/actions/workflows/iron-semi-binary-
build.yml/badge.svg?branch=iron) ](https://github.com/ros-
controls/ros2_control_demos/actions/workflows/iron-semi-binary-
build.yml?branch=iron)
|  [ 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/ros2_control_demos/tree/humble) |  [ ![Humble Binary
Build](https://github.com/ros-
controls/ros2_control_demos/actions/workflows/humble-binary-
build.yml/badge.svg?branch=humble) ](https://github.com/ros-
controls/ros2_control_demos/actions/workflows/humble-binary-
build.yml?branch=humble)
[ ![Humble Semi-Binary Build](https://github.com/ros-
controls/ros2_control_demos/actions/workflows/humble-semi-binary-
build.yml/badge.svg?branch=humble) ](https://github.com/ros-


Hardware interface is the lowest layer towards hardware in _ros2_control_ . A
hardware interface is a driver for a specific robot that exports interfaces to
the framework for controllers to use them. Overview of _ros2_control_ shows
this graphically:


Launching the Controller


This post is also available in video form - check the video link below if you
want to follow along!


#  ros-controls/ros2_control_demos


> For what it’s worth, the reason this wasn’t a problem with the old plugin is
> that it actually cheats to provide the odom transform perfectly rather than
> calculating it based on the simulated wheel spin.


1. ` ros2 launch controlko_bringup rrbot.launch.py use_mock_hardware:=false `


_ros2_control_ enables you to control the lifecycle of controllers and
hardware components. The states and transitions are the same as for the `
Lifecycle Nodes ` . Check the diagram below for more details:


5. 💻 Simulating your hardware using Gazebo Classic and Gazebo


Now that we’ve got those things tidied up a bit, we can [ move forward
](/mobile-robot-13-ros2-control-real/) with ros2_control on our robot, and
then start to run some algorithms!


wheel_separation:  0.104
wheel_radius:  0.032


[ control.ros.org ](https://control.ros.org "https://control.ros.org")


Menu


3. One joint per motor, each with a velocity command and state interface


With the ros2_control part of the JetBot defined, we can import and use this
macro in the overall JetBot definition. As we've stripped out all other
definitions, such as simulation parameters, this forms the only part of the
overall JetBot definition:


Execute the following commands to get the answers from the task:


  1. Extend ` rrbot.urdf.xacro ` with ` <gazebo> ` tags defining simulator plugins and parameters.
  2. Add hardware interface plugins under ` <ros2_control> ` tag in the file ` rrbot_macro.ros2_control.xacro ` .
  3. Add new launch file ` rrbot_sim_gazebo_class.launch.py ` for starting Gazebo Classic simulation.
  4. Add new launch file ` rrobt_sim_gazebo.launch.py ` for starting Gazebo simulation.


Clear


To see all available qualifiers, see our [ documentation
](https://docs.github.com/search-github/github-code-search/understanding-
github-code-search-syntax) .


1. Initialize the base SystemInterface class


_RRBot_ with multiple interfaces.


##  Site Terms, Privacy, and more.


**TIPP** : ` RosTeamWS ` tool has some scripts that can help you solve this
task faster. Resources:


Search


Describing the JetBot


#####  Solution:


Cancel  Submit feedback


[ ](https://github.com/)


Write a controller for _RRBot_ robot that takes joint displacements as input
and updates new joint positions for it.


To start the Gazebo simulation use:


Following this, we load the [ jetbot controller configuration
](http://localhost:3000/blog/jetbot-motors-pt2#creating-a-controller) :


###  License


The packages have following structure of subfolders:


With the robot description and the robot controller configuration loaded, we
can pass these to the [ controller manager
](http://localhost:3000/blog/jetbot-motors-pt2#creating-a-controller) :


![Josh Newans](/assets/images/logo3.png)


Now we need to pass the xacro argument in when we process the file, which is
in our robot state publisher launch file ( ` rsp.launch.py ` ).


In short, ros2_control is a control framework for ROS2. But actually, it is
much more, it is the kernel of the ROS2 system that controls robots:


* Example 7: [ "6-DOF robot" ](/ros-controls/ros2_control_demos/blob/master/example_7)


[ Mediumish Jekyll Theme ](https://www.wowthemes.net/mediumish-free-jekyll-
template/) by WowThemes.net


Branch: ` 1-robot-description/solution `


and open a new terminal and execute:


[ example_1 ](/ros-controls/ros2_control_demos/tree/master/example_1
"example_1")


Inside this block, we give the path to the [ plugin library
](http://localhost:3000/blog/jetbot-motors-pt2#code-deep-dive) , along with
the parameters needed to configure it. You may recognize the pin numbers in
this section!


  * ` bringup ` \- stores launch files and runtime configurations for demo robots.
  * ` description ` \- stores URDF (and XACRO) description files, rviz configurations and meshes for the example robots.
  * ` hardware ` \- stores implementations of example hardware components (interfaces).
  * ` controllers ` (optional) - stores implementation of example controllers.


[ example_5 ](/ros-controls/ros2_control_demos/tree/master/example_5
"example_5")


  * [ Notifications ](/login?return_to=%2Fros-controls%2Froscon2022_workshop)
  * [ Fork  23  ](/login?return_to=%2Fros-controls%2Froscon2022_workshop)
  * [ Star  91  ](/login?return_to=%2Fros-controls%2Froscon2022_workshop)


    <xacro:if value="$(arg use_ros2_control)">
        <xacro:include filename="ros2_control.xacro" />
    </xacro:if>
    <xacro:unless value="$(arg use_ros2_control)">
        <xacro:include filename="gazebo_control.xacro" />
    </xacro:unless>

---|---
`


[ example_2 ](/ros-controls/ros2_control_demos/tree/master/example_2
"example_2")


* Dr. Denis recommends you to always start to develop things first with the Mock Hardware and then start switching to simulation or real hardware. This way you save time dealing with a broken setup with simulation or hardware in the loop.


##  Folders and files


These are the lines that build the JetBot code as a library instead of a
system, and export definitions that show it is a valid plugin library to be
loaded by ros2_control. A new file, ` jetbot_control.xml ` , tells
ros2_control more information about this library to allow it to be loaded - in
this case, the library name and ros2_control plugin type (SystemInterface -
we'll discuss this more in the [ Describing the JetBot
](http://localhost:3000/blog/jetbot-motors-pt2#describing-the-jetbot)
section).


    * Which control modes are supported?
    * What happens if an incompatible controller is activated?
  4. What are the capabilities?


#####  🔩 How to test it with an off-the-shelf controller?


##  Use saved searches to filter your results more quickly


2. Add to launch file spawning (loading and activating) of controllers.


This repository aims at providing examples to illustrate ros2_control and
ros2_controllers


![Turtlebot image with arrows noting
wheels](https://assets.community.aws/a/2dkAG4luugjr8IbiSUSsZkVM0BA/turtl.webp)


ROS2 Control Concepts


  * [ C++  45.5%  ](/ros-controls/ros2_control_demos/search?l=c%2B%2B)
  * [ Python  41.3%  ](/ros-controls/ros2_control_demos/search?l=python)
  * [ CMake  6.5%  ](/ros-controls/ros2_control_demos/search?l=cmake)
  * [ C  6.5%  ](/ros-controls/ros2_control_demos/search?l=c)
  * Other  0.2%


[ example_6 ](/ros-controls/ros2_control_demos/tree/master/example_6
"example_6")


ros2 launch controlko_description view_rrbot.launch.py


Having this setup gives us a couple of options going forwards.


###  2\. 🖥 Using _Mock Hardware_ plugin for simple and generic testing of the
setup


In this case, we are defining a macro for the ros2_control part of the JetBot
that can be used in the overall robot description.


[ example_9 ](/ros-controls/ros2_control_demos/tree/master/example_9
"example_9")


**NOTE** : There are three build stages checking current and future
compatibility of the package.


[ **91** stars ](/ros-controls/roscon2022_workshop/stargazers)


#####  🗒 Setting up URDF using XACRO for a robot


##  What is _ros2_control_


[ example_11 ](/ros-controls/ros2_control_demos/tree/master/example_11
"example_11")


##  Languages


![Robot with face](/media/assets/posts/mobile-
robot/12-ros2-control/robot_with_face.png)


    * [ All features ](/features)
    * [ Documentation  ](https://docs.github.com)
    * [ GitHub Skills  ](https://skills.github.com/)
    * [ Blog  ](https://github.blog)


_RRBot_ with an exposed transmission interface.


* Example 11: [ "Car-like robot using steering controller library" ](/ros-controls/ros2_control_demos/blob/master/example_11)


3. Source build - also core ROS packages are build from source. It shows potential issues in the mid future.


You signed in with another tab or window. [ Reload ]() to refresh your
session.  You signed out in another tab or window. [ Reload ]() to refresh
your session.  You switched accounts on another tab or window. [ Reload ]() to
refresh your session.  Dismiss alert


Name  |  Name  |


git  clone  https://github.com/ros2/teleop_twist_keyboard
colcon build --symlink-install
source  install/setup.bash
ros2 run teleop_twist_keyboard teleop_twist_keyboard \
--ros-args \
-p stamped:=  true  \
-r /cmd_vel:=/jetbot_base_controller/cmd_vel


  * ` rrbot_macro.xacro ` \- macro with kinematics and geometries for the ` rrbot `
  * ` rrbot.urdf.xacro ` \- main xacro file for the robot where macro is instantiated
  * ` view_robot.launch.py ` \- loading and showing robot in ` rviz2 `


##  [ Contributors  48  ](/ros-
controls/ros2_control_demos/graphs/contributors)


  * [ Creating a new package ](https://stoglrobotics.github.io/ros_team_workspace/master/use-cases/ros_packages/create_package.html)
  * [ Setup controller package ](https://stoglrobotics.github.io/ros_team_workspace/master/use-cases/ros2_control/setup_controller.html) \- choose setup of "normal" controller


Creating A Controller


robot_controllers = PathJoinSubstitution(
[
FindPackageShare(  "jetbot_control"  ),
"config"  ,
"jetbot_controllers.yaml"  ,
]
)


[ ros2_control_demos-not-released.rolling.repos ](/ros-
controls/ros2_control_demos/blob/master/ros2_control_demos-not-
released.rolling.repos "ros2_control_demos-not-released.rolling.repos")


[ ros2_control_demo_description ](/ros-
controls/ros2_control_demos/tree/master/ros2_control_demo_description
"ros2_control_demo_description")


  * learn what is _Mock Hardware_ and how to use it
  * learn how you can fast and easily test you controller's setup and parameters before you deal with simulation or real hardware


[ controlko_description ](/ros-
controls/roscon2022_workshop/tree/master/controlko_description
"controlko_description")


##  History


4. Initialize the ` I2CDevice ` and ` Motor ` s


###  Stars


Uses repos file: ` src/$NAME$/$NAME$.repos `


linear.x.max_velocity:  0.016
linear.x.min_velocity:  -0.016
angular.z.max_velocity:  0.25
angular.z.min_velocity:  -0.25


* How is data exchanged between the controller's callbacks and the ` update ` method?


  * [ ![@christophfroehlich](https://avatars.githubusercontent.com/u/3367244?s=64&v=4) ](https://github.com/christophfroehlich)
  * [ ![@destogl](https://avatars.githubusercontent.com/u/1918204?s=64&v=4) ](https://github.com/destogl)
  * [ ![@bmagyar](https://avatars.githubusercontent.com/u/3524577?s=64&v=4) ](https://github.com/bmagyar)
  * [ ![@dependabot\[bot\]](https://avatars.githubusercontent.com/in/29110?s=64&v=4) ](https://github.com/apps/dependabot)
  * [ ![@olivier-stasse](https://avatars.githubusercontent.com/u/400341?s=64&v=4) ](https://github.com/olivier-stasse)
  * [ ![@Karsten1987](https://avatars.githubusercontent.com/u/5419873?s=64&v=4) ](https://github.com/Karsten1987)
  * [ ![@ARK3r](https://avatars.githubusercontent.com/u/22005547?s=64&v=4) ](https://github.com/ARK3r)
  * [ ![@github-actions\[bot\]](https://avatars.githubusercontent.com/in/15368?s=64&v=4) ](https://github.com/apps/github-actions)
  * [ ![@AndyZe](https://avatars.githubusercontent.com/u/11284393?s=64&v=4) ](https://github.com/AndyZe)
  * [ ![@saikishor](https://avatars.githubusercontent.com/u/10082428?s=64&v=4) ](https://github.com/saikishor)
  * [ ![@bailaC](https://avatars.githubusercontent.com/u/14002410?s=64&v=4) ](https://github.com/bailaC)
  * [ ![@jordan-palacios](https://avatars.githubusercontent.com/u/26386634?s=64&v=4) ](https://github.com/jordan-palacios)
  * [ ![@aprotyas](https://avatars.githubusercontent.com/u/34530011?s=64&v=4) ](https://github.com/aprotyas)
  * [ ![@liushuya7](https://avatars.githubusercontent.com/u/6867028?s=64&v=4) ](https://github.com/liushuya7)


[ Search syntax tips ](https://docs.github.com/search-github/github-code-
search/understanding-github-code-search-syntax)


[ doc ](/ros-controls/ros2_control_demos/tree/master/doc "doc")


###  4\. 🔬 Introspection of _ros2_control_ system


[ 329  stars ](/ros-controls/ros2_control_demos/stargazers) [ 165  forks
](/ros-controls/ros2_control_demos/forks) [ Branches  ](/ros-
controls/ros2_control_demos/branches) [ Tags  ](/ros-
controls/ros2_control_demos/tags) [ Activity  ](/ros-
controls/ros2_control_demos/activity)


* Example 3: [ "RRBot with multiple interfaces" ](/ros-controls/ros2_control_demos/blob/master/example_3)


[ Custom properties  ](/ros-controls/roscon2022_workshop/custom-properties)


###  Watchers


  3. Execute the following commands (this is one of multiple valid ways)

        ros2 control load_controller joint_trajectory_controller
    ros2 control set_controller_state joint_trajectory_controller inactive
    ros2 control switch_controllers --deactivate forward_position_controller --activate joint_trajectory_controller


From these, we use the ` on_init ` method to:


1
2
3
4
5
6
7


#  Provide feedback


The last step here is to provide a launch script to bring everything up. The
example again provides us with the launch script, including a field that
allows us to launch with mock hardware if we want - this is great for testing
that everything loads correctly on a system that doesn't have the right
hardware.


    use_ros2_control = LaunchConfiguration('use_ros2_control')

    ...

    launch_arguments={'use_sim_time': 'true', 'use_ros2_control': use_ros2_control}.items()
    ...

---|---
`


The structure of the repository follows the flow of integrating robots with
ROS2 and these are the following steps:


Secondly, we normally expect ` /cmd_vel ` to accept [ Twist
](https://docs.ros2.org/galactic/api/geometry_msgs/msg/Twist.html) messages,
but the controller expects [ TwistStamped
](https://docs.ros2.org/galactic/api/geometry_msgs/msg/TwistStamped.html)
messages. There is a parameter for ` teleop_twist_keyboard ` that turns its
messages into TwistStamped messages, but while trying it out I found that the
node ignored that parameter. Checking it out from source fixed it for me, so
in order to run the keyboard test, I recommend building and running from
source:


By Solution


No packages published


* [ GitHub Sponsors  Fund open source developers  ](/sponsors)


* Example 4: [ "Industrial robot with integrated sensor" ](/ros-controls/ros2_control_demos/blob/master/example_4)


##  Getting Started


[ Sign up
](/signup?ref_cta=Sign+up&ref_loc=header+logged+out&ref_page=%2F%3Cuser-
name%3E%2F%3Crepo-name%3E&source=header-repo&source_repo=ros-
controls%2Froscon2022_workshop)


Readme


Branch: ` 1-robot-description/task `


Finally, we ask the launched controller manager to start up the `
jetbot_base_controller ` :


[ Sign up
](/signup?ref_cta=Sign+up&ref_loc=header+logged+out&ref_page=%2F%3Cuser-
name%3E%2F%3Crepo-name%3E&source=header-repo&source_repo=ros-
controls%2Fros2_control_demos)


[ ros2_control_demos.humble.repos ](/ros-
controls/ros2_control_demos/blob/master/ros2_control_demos.humble.repos
"ros2_control_demos.humble.repos")


[ example_3 ](/ros-controls/ros2_control_demos/tree/master/example_3
"example_3")


To try the package out, we first need a working JetBot. If you're not sure how
to do the initial setup, I've created a video on exactly that:


##  Content


Branch: ` 7-robot-hardware-interface/task `


First, before talking about any of these concepts, there's an important
distinction to make: [ ROS Control ](http://wiki.ros.org/ros_control) and [
ROS2 Control ](https://control.ros.org/master/index.html) are _different
frameworks_ , and are not compatible with one another. This post is focused on
ROS2 Control - or as their documentation calls it, ros2_control.


class  JetBotSystemHardware  :  public  hardware_interface::SystemInterface {


    * [ CI/CD & Automation ](/solutions/ci-cd/)
    * [ DevOps ](/solutions/devops/)
    * [ DevSecOps  ](https://resources.github.com/devops/fundamentals/devsecops/)


Additional navigation options


This line is just constructing a command that could be typed into a terminal,
but instead it’s going to run it inside the launch script and use the output.
We can see that ` use_ros2_control ` (a ` LaunchConfiguration ` argument) is
used in this call, so at runtime it will substitute that for whatever is
passed in, then substitute the result of the whole command into the `
robot_description_config ` variable as a string.


#  ros-controls/roscon2022_workshop


[ Activity  ](/ros-controls/ros2_control_demos/activity)


  2. Execute in another terminal:

        ros2 control list_controllers
    ros2 service call /controller_manager/list_hardware_components controller_manager_msgs/srv/ListHardwareComponents {}


In this post, I show the next step in making ROS2 Control work with the
WaveShare JetBot - wrapping the motor control code in a System. I'll walk
through some concepts, show the example repository for ROS2 Control
implementations, and then show how to implement the System for JetBot and see
it running.


ros2_control is integrated with simulators using simulator-specific plugins.
Those plugins extend controller manager with simulator-related functionalities
and enables loading hardware interfaces that are created specifically for the
simulator. Simulators are using description under ` <ros2_control> ` to setup
the interfaces. They are searched for interfaces with standard names, `
position ` , ` velocity ` and ` effort ` , to wire them with the internal
simulator-states.


[ AWS Heroes  ](https://aws.amazon.com/developer/community/heroes/?community-
heroes-all.sort-by=item\[…\]location=*all&awsf.filter-year=*all&awsf.filter-
activity=*all)


{{ message }}


For all of the concepts in ros2_control, the actual implementation of a System
is quite simple. Our ` JetBotSystemHardware ` class extends the
SystemInterface class:


[ example_12 ](/ros-controls/ros2_control_demos/tree/master/example_12
"example_12")


Published  Mar 18, 2024


[ example_9 ](/ros-controls/ros2_control_demos/tree/master/example_9
"example_9")


###  Stars


Search for content


#  ROSCon 2022 workshop on ros2_control


The first step is to update your URDF to match your physical robot (if you
have one). In my case I did the following:


The SystemInterface then comes into play when _describing_ the robot. The `
description ` folder from the example contains the files that define the
robot, including its ros2_control configuration, simulation configuration, and
materials used to represent it during simulation. As this implementation has
been pared down to basics, only the ros2_control configuration with mock
hardware flag have been kept in.


28 Sep 2022


` ` Ctrl ` ` K ` `


[ roscon2022_workshop.repos ](/ros-
controls/roscon2022_workshop/blob/master/roscon2022_workshop.repos
"roscon2022_workshop.repos")


The concepts in this package are demonstrated on the examples of _RRBot_ and
_DiffBot_ . Those two world-known imaginary robots are trivial simulations to
demonstrate and test ` ros2_control ` concepts.


    <xacro:arg name="use_ros2_control" default="true"/>

---|---
`


1
2
3
4
5
6
7
8
9
10


###  3\. ⚙ Getting know the roles of the main components of _ros2_control_
framework


**TIPP** : ` RosTeamWS ` tool has some scripts that can help you to solve this
task faster (on the branch is this already implemented). Resources:


**NOTE** : Currently, there is only ` GenericSystem ` mock component, which
can mock also sensor or actuator components (because they just have a reduced
feature set compared to a system).


This commit does not belong to any branch on this repository, and may belong
to a fork outside of the repository.


* Product


Let's take an example: the Turtlebot and the [ JetBot
](https://www.nvidia.com/en-us/autonomous-machines/embedded-systems/jetbot-ai-
robot-kit/) are both driven using one wheel on each side and casters to keep
the robots level. These are known as differential drive robots.


[ ![logo](/img/Logo_light.svg) ](/)


Skip to content


##  Problem 1 - Gazebo clock rate


First, we now expect messages to go to ` /jetbot_base_controller/cmd_vel `
topic instead of the previous ` /cmd_vel ` topic. We can fix that by asking `
teleop_twist_keyboard ` to remap the topic it normally publishes to.


#####  Solution


You signed in with another tab or window. [ Reload ]() to refresh your
session.  You signed out in another tab or window. [ Reload ]() to refresh
your session.  You switched accounts on another tab or window. [ Reload ]() to
refresh your session.  Dismiss alert


1
2
3
4
5
6
7
8
9


[ Report repository ](/contact/report-
content?content_url=https%3A%2F%2Fgithub.com%2Fros-
controls%2Fros2_control_demos&report=ros-controls+%28user%29)


    * [ Actions  Automate any workflow  ](/features/actions)
    * [ Packages  Host and manage packages  ](/features/packages)
    * [ Security  Find and fix vulnerabilities  ](/features/security)
    * [ Codespaces  Instant dev environments  ](/features/codespaces)
    * [ Copilot  Write better code with AI  ](/features/copilot)
    * [ Code review  Manage code changes  ](/features/code-review)
    * [ Issues  Plan and track work  ](/features/issues)
    * [ Discussions  Collaborate outside of code  ](/features/discussions)


JetBot System Implementation


This System class, plus the ` I2CDevice ` and ` Motor ` classes, are compiled
into the plugin library, ready to be loaded by the controller.


# Get URDF via xacro
robot_description_content = Command(
[
PathJoinSubstitution([FindExecutable(name=  "xacro"  )]),
" "  ,
PathJoinSubstitution(
[FindPackageShare(  "jetbot_control"  ),  "urdf"  ,  "jetbot.urdf.xacro"  ]
),
" "  ,
"use_mock_hardware:="  ,
use_mock_hardware,
]
)
robot_description = {  "robot_description"  : robot_description_content}


In this excercise we will focus on setting up the description using the XACRO
format which is highly configurable and parameterizable and generally better
to use than the static URDF format.


[ \+ 34 contributors ](/ros-controls/ros2_control_demos/graphs/contributors)


* Example 9: [ "Gazebo simulation" ](/ros-controls/ros2_control_demos/blob/master/example_9)


    vcs import --input roscon2022_workshop/roscon2022_workshop.repos .
    rosdep update
    rosdep install -y -i --from-paths .


The repository is structured into ` example_XY ` folders that fully contained
packages with names ` ros2_control_demos_example_XY ` .


[ 91  stars ](/ros-controls/roscon2022_workshop/stargazers) [ 23  forks
](/ros-controls/roscon2022_workshop/forks) [ Branches  ](/ros-
controls/roscon2022_workshop/branches) [ Tags  ](/ros-
controls/roscon2022_workshop/tags) [ Activity  ](/ros-
controls/roscon2022_workshop/activity)


  * ` bringup/launch/<example_name>.launch.py ` \- launch file for the example
  * ` bringup/config/<example_name>_controllers.yaml ` \- parameters with controllers' setup for the example.
  * ` description/<example_name>.ros2_control.xacro ` \- XACRO file with ` ros2_control ` -URDF-tag with hardware setup and parameters.
  * ` description/<example_name>.urdf.xacro ` \- the main description for for the example used to generate URDF on the fly that is published on the ` /robot_description ` topic.
  * ` hardware/<example_name>.hpp ` \- header file of the example hardware component implementation.
  * ` hardware/<example_name>.cpp ` \- source file with the example hardware component implementation.
  * ` controllers/<example_name>.hpp ` \- header file of the example controller implementation.
  * ` controllers/<example_name>.cpp ` \- source file with the example controller implementation.


master


**Gazebo Classic**


[ ros2_control_demos.iron.repos ](/ros-
controls/ros2_control_demos/blob/master/ros2_control_demos.iron.repos
"ros2_control_demos.iron.repos")


[ **329** stars ](/ros-controls/ros2_control_demos/stargazers)


One last thing I did was to set up RViz the way I liked it and saved the
configuration to the ` config ` directory so that it can be loaded back up
again in future with ` rviz2 -d ` .


![Sphere collision](/media/assets/posts/mobile-
robot/12-ros2-control/sphere_collision.png)


First, we stripped out a lot of configuration that supported simulation - we
could add this back in to support Gazebo simulation, where the robot in the
simulation should act nearly identically to the real life robot. This allows
us to start developing robotics applications purely in simulation, which is
likely to be faster due to the reset speed of the simulation, lack of hardware
requirements, and so on.


Given that we have these issues, we might sometimes want to swap back to the
old control method. It generally tends to work a bit more “perfectly” which is
not always what we want but can be handy.


    1
    2


###  8\. 🛂 How to write a controller


Explore


2. Read the pin configuration used for connecting to the motors from the parameters


[ **23** forks ](/ros-controls/roscon2022_workshop/forks)


[ Notifications ](/login?return_to=%2Fros-controls%2Froscon2022_workshop)


1
2
3
4


This commit does not belong to any branch on this repository, and may belong
to a fork outside of the repository.


1. Add ` hardware ` tag under the ` ros2_control ` tag with plugin ` mock_components/GenericSystem ` and set ` mock_sensor_commands ` parameter. The parameter create fake command interface for sensor values than enables you to simulate the values on the sensor.


[ .github ](/ros-controls/ros2_control_demos/tree/master/.github ".github")


The example shows how to implement robot hardware with separate communication
to each actuator.


Answers to the questions:


  4. Execute the following commands (this is one of multiple valid ways)

        # stop controller
    ros2 control switch_controllers --deactivate joint_trajectory_controller
    # get component name
    ros2 service call /controller_manager/list_hardware_components controller_manager_msgs/srv/ListHardwareComponents {}
    # set component state
    ros2 service call /controller_manager/set_hardware_component_state controller_manager_msgs/srv/SetHardwareComponentState "
    name: rrbot
    target_state:
     id: 0
     label: inactive"
    # check internals of ros2_control
    ros2 control list_controllers
    ros2 control list_hardware_interfaces


5. The System connects to the I2C bus, and hence, the motors


Apache-2.0 license


ros2_control also provides the controller manager, which is used to manage
resources and activate/deactivate controllers, to allow for advanced
functionality like switching between controllers. Our use case is simple, so
we will only use it to activate the controller. This architecture is explained
well in the ros2_control documentation - see the [ architecture page
](https://control.ros.org/master/doc/getting_started/getting_started.html#architecture)
for more information.


Now it’s time for problem number 3, which I currently don’t have a fix for,
and if someone can figure out what’s going on, I’ll be very grateful. I have a
[ whole GitHub repo ](https://github.com/joshnewans/mwe_diffdrive_bug) and
separate video for reproducing it.


The important files to check in each example are:


For any robot that is used with ROS/ROS2 an URDF description is needed. This
description holds information about kinematics, visualization (e.g., for
Rviz2) and collision data. This description is also used by popular ROS2 high-
level libraries like, MoveIt2, Nav2 and Simulators.


    * [ All features ](/features)
    * [ Documentation  ](https://docs.github.com)
    * [ GitHub Skills  ](https://skills.github.com/)
    * [ Blog  ](https://github.blog)


#  Search code, repositories, users, issues, pull requests...


#####  Task


[ roscon2022_workshop.humble.repos ](/ros-
controls/roscon2022_workshop/blob/master/roscon2022_workshop.humble.repos
"roscon2022_workshop.humble.repos")


    * Check the definition of [ ` JointJog ` message ](https://github.com/ros-controls/control_msgs/blob/galactic-devel/control_msgs/msg/JointJog.msg)
    * Alternatively use the CLI command: ` ros2 interface show control_msgs/msg/JointJog `
    * Use [ Writing a new controller manual ](https://control.ros.org/master/doc/ros2_controllers/doc/writing_new_controller.html) to implement the controller


#  Making a Mobile Robot #12a - ros2_control extra bits


Repositories


[ ros-controls ](/ros-controls) /  **[ roscon2022_workshop ](/ros-
controls/roscon2022_workshop) ** Public


    use_sim_time = LaunchConfiguration('use_sim_time')
    use_ros2_control = LaunchConfiguration('use_ros2_control')

---|---
`


to view the robot and move its joints using the ` Joint State Publisher ` GUI.


[ ros2_control_demo_description ](/ros-
controls/ros2_control_demos/tree/master/ros2_control_demo_description
"ros2_control_demo_description")


[ Sign in ](/login?return_to=https%3A%2F%2Fgithub.com%2Fros-
controls%2Fros2_control_demos)


Skip to content


2. A ros2_control xacro file, describing the plugin to load and the parameters to give it


[ roscon2022_workshop.repos ](/ros-
controls/roscon2022_workshop/blob/master/roscon2022_workshop.repos
"roscon2022_workshop.repos")


Search


[ README.md ](/ros-controls/ros2_control_demos/blob/master/README.md
"README.md")


1. We launch the JetBot launch file defined in the package


#####  Solution:


3. ` read ` / ` write ` : methods called every controller update. ` read ` is for reading the velocities from the motors, and ` write ` is for writing requested speeds into the motors.


* Solutions


    * [ Enterprise ](/enterprise)
    * [ Teams ](/team)
    * [ Startups ](/enterprise/startups)
    * [ Education  ](https://education.github.com)


###  Resources


#####  GOAL


  * [ Terms ](https://docs.github.com/site-policy/github-terms/github-terms-of-service)
  * [ Privacy ](https://docs.github.com/site-policy/privacy-policies/github-privacy-statement)
  * [ Security ](/security)
  * [ Status ](https://www.githubstatus.com/)
  * [ Docs ](https://docs.github.com/)
  * [ Contact ](https://support.github.com?tags=dotcom-footer)
  * Manage cookies
  * Do not share my personal information


Execute the following commands to see the new controller running:


That's all for this stage - we have successfully integrated our JetBot's
motors into a ros2_control System interface!


##  Footer


The ` jetbot.ros2_control.xacro ` file defines the ros2_control configuration
needed to control the robot. It uses ` xacro ` files to define this
configuration, where ` xacro ` is a tool that extends XML files by allowing us
to define macros that can be referenced in other files:


[ example_8 ](/ros-controls/ros2_control_demos/tree/master/example_8
"example_8")


Start the previous example one more time and try to answer the following
questions:


Hardware:


[ Generative AI  ](/generative-ai)


[ ros2_control_demos ](/ros-
controls/ros2_control_demos/tree/master/ros2_control_demos
"ros2_control_demos")


[ Notifications ](/login?return_to=%2Fros-controls%2Fros2_control_demos)


ros2_control uses joints to understand what the movable parts of a robot are.
In our case, we define one joint for each motor.


4. 🔬 Introspection of the _ros2_control_ system


So the ` params ` is now taking in a string. But because it is a part of the
clever ROS Launch system, instead of a string it can also take a
_substitution_ . So we’ll take advantage of the ` Command ` substitution, and
replace the ` robot_description_config ` assignment to a call out to the `
xacro ` process rather than the Python module. Make sure you also add the
appropriate ` import ` at the top.


* [ Pricing ](/pricing)


Toggle navigation


    1
    2
    3


* Open Source


[ robotics ](/topics/robotics "Topic: robotics") [ ros ](/topics/ros "Topic:
ros") [ rrbot ](/topics/rrbot "Topic: rrbot") [ ros2-control
](/topics/ros2-control "Topic: ros2-control") [ ros2-controllers
](/topics/ros2-controllers "Topic: ros2-controllers")


This has probably all been a bit confusing, so check out the final files
below.


At the end of the previous tutorial I mentioned that there are a few problems
with the simulation. The first of these is that you’ll notice the robot motion
in RViz is quite “choppy” while driving the robot around. That’s because the
Gazebo-ROS clock is only running at 10Hz, so the rest of ROS gets locked to
that slow speed. We need to tell Gazebo to publish the clock faster. This
isn’t only a visual thing, it’s actually causing our odometry to drift quite
badly (but don’t check that now because there are other problems affecting it
too which we’ll fix soon).


**TIPP** : ` RosTeamWS ` tool has some scripts that can help you to solve this
task faster. Resources:


[ control.ros.org ](https://control.ros.org "https://control.ros.org")


[ example_4 ](/ros-controls/ros2_control_demos/tree/master/example_4
"example_4")


1
2
3
4
5
6


* Example 14: [ "Modular robots with actuators not providing states and with additional sensors" ](/ros-controls/ros2_control_demos/blob/master/example_14)


#####  Task


It could be to do with acceleration limits, I have tried to experiment with
this too with no success. Keeping accelerations and velocities low reduces the
effect, which may be useful in testing.


    1. 🛠 How to setup _Mock Hardware_ for a robot?
    2. 🔩 How to test it with an off-the-shelf controller?
  3. ⚙ Getting to know the roles of the main components of the _ros2_control_ framework: _Controller Manager_ , _Controllers_ , _Resource Manager_ and _Hardware Interface_


[ ](/ros-controls/ros2_control_demos/branches) [ ](/ros-
controls/ros2_control_demos/tags)


1. 📑 Setting up the hardware description for _ros2_control_


Controllers in _ros2_control_ are serving on the one hand as "interfaces"
towards the ROS-world and on the other hand implement algorithms to control
the hardware. A controller, when activated, gets loaned access to the exported
hardware interface to read and write values directly from/to memory locations
that the hardware interface is using. Although somewhat limited, this concept
enables deterministic and reliable data flow between controllers and hardware
interfaces (drivers).


1
2
3
4


[ Home  ](/) [ Tags  ](/tags)


[ Activity  ](/ros-controls/roscon2022_workshop/activity)


[ Josh Newans ](https://articulatedrobotics.xyz/) [ Follow
](https://www.facebook.com/ArticulatedRobotics/)
Creator of Articulated Robotics.


  * Package: ` gz_ros2_control `
  * Simulator plugin: ` libign_ros2_control-system.so `
  * HW interface plugin: ` ign_ros2_control/IgnitionSystem ` **NOTE** ` ign ` will be switched to ` gz ` very soon!


Name


This is fine, and works as is, but ideally we want to be able to set it at the
level above this, to pass it in as a _launch argument_ and because of how
launch files are processed, dropping a ` LaunchConfiguration ` variable in
here like we did with ` use_sim_time ` just won’t work.


Branch: ` 8-write-controller/solution `


After cloning the repository, go to your source workspace and execute the
following commands to import the necessary repositories and to install all
dependencies:


You can’t perform that action at this time.


1
2
3


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


[ CONTRIBUTING.md ](/ros-
controls/ros2_control_demos/blob/master/CONTRIBUTING.md "CONTRIBUTING.md")


I don’t think it’s a friction issue, as I have tried to eliminate that. It
seems more like a timing issue, but the odd thing is that the laser data moves
in the direction of rotation, not away from it, suggesting that the transforms
are being published _earlier_ than the sensor data rather than later (so it’s
not just be a delay in ros2_control).


All we need to do is in our left/right wheel links of our URDF, in the `
collision ` geometry (not visual!) replace ` cylinder ` with ` sphere ` and
remove the ` length ` parameter. To check this we can enable collision view in
Gazebo to see the collision sphere and the visual cylinder.


##  Languages


#####  Task


* Controller accepts a command only once.


  * [ Commonly used robot-package structure ](https://stoglrobotics.github.io/ros_team_workspace/master/guidelines/robot_package_structure.html)
  * [ Creating a new package ](https://stoglrobotics.github.io/ros_team_workspace/master/use-cases/ros_packages/create_package.html)
  * [ Setting up robot bringup ](https://stoglrobotics.github.io/ros_team_workspace/master/use-cases/ros_packages/setup_robot_bringup_package.html)


4. The differential drive controller loads the JetBot System as a plugin library


* [ The ReadME Project  GitHub community articles  ](/readme)


Branch: ` 5-simulation `


  * [ __ ](https://twitter.com/intent/tweet?text=Making a Mobile Robot #12a - ros2_control extra bits&url=https://articulatedrobotics.xyz/mobile-robot-12a-ros2-control-extra/)
  * [ __ ](https://facebook.com/sharer.php?u=https://articulatedrobotics.xyz/mobile-robot-12a-ros2-control-extra/)
  * [ __ ](https://www.linkedin.com/shareArticle?mini=true&url=https://articulatedrobotics.xyz/mobile-robot-12a-ros2-control-extra/)


With the JetBot working, we can create a workspace and clone the code into it.
Use VSCode over SSH to execute the following commands:


By Solution


The example shows a simple chainable controller and its integration to form a
controller chain to control the joints of _RRBot_ .


  * _ros2_control_ is now using PickNik's [ generate_parameter_library ](https://github.com/PickNikRobotics/generate_parameter_library) so simpler and cleaner parameters usage and definition.
    * parameters are defined in [./src/displacement_controller.yaml] file
    * example controller setup is in:
      * [./test/displacement_controller_params.yaml] - when controller is used directly with the hardware
      * [./test/displacement_controller_preceeding_params.yaml] - when controller is used at the beginning of the chain (see the next task for details!)


6. 🔃 Become familiar with the lifecycle of controllers and hardware. Learn how to use them.


With this, we have described how to configure a controller manager with a
differential drive controller to control our JetBot!


private  :
std::vector<MotorPins> motor_pin_sets_;
std::vector<Motor> motors_;
std::shared_ptr<I2CDevice> i2c_device_;
std::vector< double  > hw_commands_;
std::vector< double  > hw_velocities_;


###  License


The next problem we have is wheel drift. The easiest way to spot this is to do
a fresh start on Gazebo/RViz, and do a full revolution of the robot. We should
see that when we come back to the initial angle in Gazebo, RViz is no longer
in sync.


We define that the controller is open loop, as there is no feedback. We give
the names of the joints for the controller to control - this is how the
controller knows it can send velocities to the two wheels implemented by our
system class. We also set velocity limits on both linear and angular movement:


For


Now we need to add a conditional to change which bit of the URDF is used.
Xacro doesn’t have an ` if-else ` construct that we may be familiar with,
instead it has ` if ` and ` unless ` which will trigger depending on whether
the condition is true, or untrue. So down where we have our `
gazebo_control.xacro ` commented out, we instead want to add the following
blocks:


[ Dockerfile ](/ros-controls/ros2_control_demos/tree/master/Dockerfile
"Dockerfile")


[ controlko_bringup ](/ros-
controls/roscon2022_workshop/tree/master/controlko_bringup
"controlko_bringup")


![Articulated Robotics](/assets/images/logo2.png)


The launch script goes through a few steps to get to the full ros2_control
system, starting with loading the [ robot description
](http://localhost:3000/blog/jetbot-motors-pt2#describing-the-jetbot) . We
specify the path to the description file relative to the package, and use the
` xacro ` tool to generate the full XML for us:


[ ](/ros-controls/roscon2022_workshop/branches) [ ](/ros-
controls/roscon2022_workshop/tags)


[ ros2_control_demos-not-released.humble.repos ](/ros-
controls/ros2_control_demos/blob/master/ros2_control_demos-not-
released.humble.repos "ros2_control_demos-not-released.humble.repos")


[ Adrian Rosebrock ](http://www.pyimagesearch.com/author/adrian/ "Posts by
Adrian Rosebrock") provides a series of [ image processing utilities
](https://github.com/jrosebr1/imutils) . One function,  [ range-detector
](https://github.com/jrosebr1/imutils/blob/master/bin/range-detector "range-
detector") , allows the user to threshold each channel of an RGB or HSV image
and preview the result in real-time. Run this script on each of the sample
photos and try to determine the best values for each channel. The resulting
image should have the lane lines detected while limiting noise and other
objects as much as possible. Remember that the image processing pipeline will
remove portions of the image outside the specified region of interest so don’t
be too concerned with false positives outside the ROI. Run the program using
the following command in the directory where you saved the range-detector
file.


  * [ nodelet_topic_tools ](/nodelet_topic_tools?distro=kinetic)
  * [ roscpp ](/roscpp?distro=kinetic)
  * [ sensor_msgs ](/sensor_msgs?distro=kinetic)

** Used by  (18) **

  * [ astra_launch ](/astra_launch?distro=kinetic)
  * [ avt_vimba_camera ](/avt_vimba_camera?distro=kinetic)
  * [ cob_bringup ](/cob_bringup?distro=kinetic)
  * [ freenect_launch ](/freenect_launch?distro=kinetic)
  * [ image_pipeline ](/image_pipeline?distro=kinetic)
  * [ mobility_base_bringu... ](/mobility_base_bringup?distro=kinetic)
  * [ open_manipulator_ar_... ](/open_manipulator_ar_markers?distro=kinetic)
  * [ openni2_launch ](/openni2_launch?distro=kinetic)
  * [ opt_camera ](/opt_camera?distro=kinetic)
  * [ pointgrey_camera_dri... ](/pointgrey_camera_driver?distro=kinetic)
  * [ pr2_gazebo ](/pr2_gazebo?distro=kinetic)
  * [ rgbd_launch ](/rgbd_launch?distro=kinetic)
  * [ roseus_tutorials ](/roseus_tutorials?distro=kinetic)
  * [ spinnaker_camera_dri... ](/spinnaker_camera_driver?distro=kinetic)
  * [ stereo_image_proc ](/stereo_image_proc?distro=kinetic)
  * [ visp_hand2eye_calibr... ](/visp_hand2eye_calibration?distro=kinetic)
  * [ visp_tracker ](/visp_tracker?distro=kinetic)
  * [ xiaoqiang_freenect_l... ](/xiaoqiang_freenect_launch?distro=kinetic)


  image_proc

![Monocular image
node](/image_proc/cturtle?action=AttachFile&do=get&target=image_proc.png)

De-mosaics and undistorts the raw camera image stream.

All processing is on demand. Color processing is performed only if there is a
subscriber to a color topic. Rectification is performed only if there is a
subscriber to a rectified topic. While there are no subscribers to output
topics, ` image_proc ` unsubscribes from the ` image_raw ` and ` camera_info `
topics.

[ image_transport ](/image_transport) is used for all publications and
subscriptions.


  Arguments

` manager ` ( ` string ` )

  * The name of the target nodelet manager. It will need to be globally qualified (e.g. ` /my_manager ` ), unless the manager is already in the camera namespace.

` respawn ` ( ` bool ` , default: false)

  * If true, enables bond topics and respawns any nodelet loaders that die. If the manager also respawns, the system is robust to any node dying. However, the proliferation of bond topics can overwhelm introspection tools like [ rxgraph ](/rxgraph) .


[ ![ROS RasPiCam Lane Detection Output Image]( https://s3-us-
west-2.amazonaws.com/selbystorage/wp-
content/uploads/2017/July/ros_driverless_car_kitchen_processed_image.png) ](
https://s3-us-west-2.amazonaws.com/selbystorage/wp-
content/uploads/2017/July/ros_driverless_car_kitchen_processed_image.png)


    $ roslaunch raspicam_node camerav2_320x240.launch
    $ rosrun image_transport republish compressed in:=/raspicam_node/image raw out:=/raspicam_node/image
    $ rosrun camera_calibration cameracalibrator.py --size 8x6 --square 0.74 image:=/raspicam_node/image camera:=/raspicam_node


We now need to tell rviz which fixed frame we want to use. In the 'Displays'
group, under the 'Global Options' item, click the frame label next to 'Fixed
Frame'. Type in or select '/pelvis'. You should now see your robot model from
a distance.