Writing a Hardware Component
In ros2_control hardware system components are libraries, dynamically loaded by the controller manager using the pluginlib interface. The following is a step-by-step guide to create source files, basic tests, and compile rules for a new hardware interface.
If the package for the hardware interface does not exist, then create it first. The package should have
ament_cmakeas a build type. The easiest way is to search online for the most recent manual. A helpful command to support this process is
ros2 pkg create. Use the
--helpflag for more information on how to use it. There is also an option to create library source files and compile rules to help you in the following steps.
Preparing source files
After creating the package, you should have at least
package.xmlfiles in it. Create also
srcfolders if they do not already exist. In
srcfolder. Optionally add
visibility_control.hwith the definition of export rules for Windows. You can copy this file from an existing controller package and change the name prefix to the
Adding declarations into header file (.hpp)
Take care that you use header guards. ROS2-style is using
#definepreprocessor directives. (For more information on this, a search engine is your friend :) ).
visibility_control.hif you are using one.
Systemdepending on the type of hardware you are using. for more details about each type check Hardware Components description.
Define a unique namespace for your hardware_interface. This is usually the package name written in
Define the class of the hardware_interface, extending
$InterfaceType$Interface, e.g., .. code:: c++ class HardwareInterfaceName : public hardware_interface::$InterfaceType$Interface
5. Add a constructor without parameters and the following public methods implementing
on_error; and overriding
write. For further explanation of hardware-lifecycle check the pull request and for exact definitions of methods check the
"hardware_interface/$interface_type$_interface.hpp"header or doxygen documentation for Actuator, Sensor or System.
Adding definitions into source file (.cpp)
Include the header file of your hardware interface and add a namespace definition to simplify further development.
on_initmethod. Here, you should initialize all member variables and process the parameters from the
infoargument. In the first line usually the parents
on_initis called to process standard values, like name. This is done using:
hardware_interface::(Actuator|Sensor|System)Interface::on_init(info). If all required parameters are set and valid and everything works fine return
on_configuremethod where you usually setup the communication to the hardware and set everything up so that the hardware can be activated.
on_cleanupmethod, which does the opposite of
export_command_interfacesmethods where interfaces that hardware offers are defined. For the
Sensor-type hardware interface there is no
export_command_interfacesmethod. As a reminder, the full interface names have structure
(optional) For Actuator and System types of hardware interface implement
perform_command_mode_switchif your hardware accepts multiple control modes.
on_activatemethod where hardware “power” is enabled.
on_deactivatemethod, which does the opposite of
on_shutdownmethod where hardware is shutdown gracefully.
on_errormethod where different errors from all states are handled.
readmethod getting the states from the hardware and storing them to internal variables defined in
writemethod that commands the hardware based on the values stored in internal variables defined in
IMPORTANT: At the end of your file after the namespace is closed, add the
For this you will need to include the
"pluginlib/class_list_macros.hpp"header. As first parameters you should provide exact hardware interface class, e.g.,
<my_hardware_interface_package>::<RobotHardwareInterfaceName>, and as second the base class, i.e.,
Writing export definition for pluginlib
<my_hardware_interface_package>.xmlfile in the package and add a definition of the library and hardware interface’s class which has to be visible for the pluginlib. The easiest way to do that is to check definition for mock components in the hardware_interface mock_components section.
Usually, the plugin name is defined by the package (namespace) and the class name, e.g.,
<my_hardware_interface_package>/<RobotHardwareInterfaceName>. This name defines the hardware interface’s type when the resource manager searches for it. The other two parameters have to correspond to the definition done in the macro at the bottom of the
Writing a simple test to check if the controller can be found and loaded
Create the folder
testin your package, if it does not exist already, and add a file named
You can copy the
load_generic_system_2dofcontent defined in the test_generic_system.cpp package.
Change the name of the copied test and in the last line, where hardware interface type is specified put the name defined in
Add compile directives into ``CMakeLists.txt`` file
Under the line
find_package(ament_cmake REQUIRED)add further dependencies. Those are at least:
Add a compile directive for a shared library providing the
<robot_hardware_interface_name>.cppfile as the source.
Add targeted include directories for the library. This is usually only
Add ament dependencies needed by the library. You should add at least those listed under 1.
Export for pluginlib description file using the following command: .. code:: cmake
Add install directives for targets and include directory.
In the test section add the following dependencies:
Add compile definitions for the tests using the
ament_add_gmockdirective. For details, see how it is done for mock hardware in the ros2_control package.
(optional) Add your hardware interface`s library into
Add dependencies into ``package.xml`` file
Add at least the following packages into
Add at least the following package into
Compiling and testing the hardware component
Now everything is ready to compile the hardware component using the
colcon build <my_hardware_interface_package>command. Remember to go into the root of your workspace before executing this command.
If compilation was successful, source the
setup.bashfile from the install folder and execute
colcon test <my_hardware_interface_package>to check if the new controller can be found through
pluginliblibrary and be loaded by the controller manager.
That’s it! Enjoy writing great controllers!
Useful External References
The script is currently only recommended to use for Foxy, not compatible with the API from Galactic and onwards.