Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gpio command controller #1251

Merged
merged 68 commits into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
5fecf27
added gpio_command_controller
mcbed Nov 2, 2022
6ffda9d
added doc to gpio controllers
mcbed Nov 2, 2022
f88fc7d
changed parameter interface_names to command_interfaces
mcbed Nov 2, 2022
56fc1e5
added test
mcbed Nov 2, 2022
9e73ab7
code formating
mcbed Nov 2, 2022
1cbd3a6
added gpio state publisher
Nov 2, 2022
7228e06
fixed broken node_state
Nov 2, 2022
880aeea
added DynamicJointState message for Gpio state
Nov 2, 2022
94befb0
fixed tests and added gpio state tests
Nov 2, 2022
882c936
fixed format
Nov 16, 2022
efce87a
Apply pre-commit fix
Wiktor-99 Jul 31, 2024
b53bff6
Fix compilation on ros rolling
Wiktor-99 Aug 1, 2024
67b6069
Add parameters file, use generated gpio_command_controller_parameters…
Wiktor-99 Aug 3, 2024
30d2604
Remove unnecessary members: interface_names_, gpios_names_ and use pa…
Wiktor-99 Aug 4, 2024
4c824e8
Refactor of storing interface types
Wiktor-99 Aug 4, 2024
dd86d9e
Remove unnecessary includes
Wiktor-99 Aug 4, 2024
4ac938d
Refacotr on_activate method. Add validate_configured_interfaces and i…
Wiktor-99 Aug 4, 2024
aa59297
Refactor update method, split update of state if and command if
Wiktor-99 Aug 4, 2024
6276617
Move test fixture form hpp to cpp
Wiktor-99 Aug 4, 2024
66bd971
Update docks and package.xml
Wiktor-99 Aug 4, 2024
7b70159
Add state validation
Wiktor-99 Aug 4, 2024
58c1afc
Store command and state ifs in the map
Wiktor-99 Aug 5, 2024
e5c65db
Use interface maps for command and state update. Use DynamicJointStat…
Wiktor-99 Aug 5, 2024
0dc5c87
Use ordered state if vector instead of map
Wiktor-99 Aug 6, 2024
765a3cb
Restore state if validation
Wiktor-99 Aug 6, 2024
a1c8fa3
Align logging
Wiktor-99 Aug 6, 2024
de8acba
Update code layout
Wiktor-99 Aug 7, 2024
aebbf0b
Simplifie test fixture
Wiktor-99 Aug 7, 2024
0deb417
Update tests. Stop using pointer, set members as public
Wiktor-99 Aug 7, 2024
3e7a12a
Add set of test for init
Wiktor-99 Aug 9, 2024
373053e
Add setup_command_and_state_interfaces as refactor UTs
Wiktor-99 Aug 13, 2024
1dc481f
Add two UTs to check wrong ifs assing
Wiktor-99 Aug 15, 2024
2bad07b
Add create node option function and remove redundant test
Wiktor-99 Aug 15, 2024
f78158e
Extract redundant code to methods
Wiktor-99 Aug 15, 2024
815f85e
Reafactor command UTs
Wiktor-99 Aug 16, 2024
0265503
Add two UTs for different commands
Wiktor-99 Aug 16, 2024
28db5aa
Add one more test with command with different ports order
Wiktor-99 Aug 16, 2024
4be8fac
Add UT for the wrong gpio/port name in the command
Wiktor-99 Aug 17, 2024
fc10ad5
Update package.xml
Wiktor-99 Aug 17, 2024
1ac37e4
Merge branch 'master' into gpio_controllers
Wiktor-99 Aug 17, 2024
e89d814
Update pkg version
Wiktor-99 Aug 22, 2024
9c90fb2
Fix includes
Wiktor-99 Aug 22, 2024
c165c1d
Fix linters
Wiktor-99 Aug 24, 2024
dd19879
Update toctree, add gpio controller info
Wiktor-99 Aug 24, 2024
b3d9ef4
Merge branch 'master' into gpio_controllers
Wiktor-99 Aug 26, 2024
4b60038
Merge branch 'master' into gpio_controllers
Wiktor-99 Sep 9, 2024
9fb380a
Merge branch 'master' into gpio_controllers
Wiktor-99 Sep 22, 2024
a2b1f4f
Merge branch 'master' into gpio_controllers
bmagyar Sep 26, 2024
b2eab6a
Merge branch 'master' into gpio_controllers
christophfroehlich Nov 3, 2024
510d847
Rename parameter and update docs
christophfroehlich Nov 3, 2024
4518b58
Set parameter read-only
christophfroehlich Nov 3, 2024
071e190
Update docs and improve error message
christophfroehlich Nov 3, 2024
fdfe17b
Fix tests
christophfroehlich Nov 3, 2024
8a8cd04
Merge pull request #2 from ros-controls/gpio_controllers
Wiktor-99 Nov 4, 2024
1e61111
Parametrize state interfaces
Wiktor-99 Nov 4, 2024
9929eb1
Parse URDF to get gpio state interfaces, add test and docs
Wiktor-99 Nov 4, 2024
13ba72b
Remove urdf model from controller
Wiktor-99 Nov 5, 2024
a8228af
Update docs after review
Wiktor-99 Nov 7, 2024
7bf2d4e
Create command subscriber only when any command interface is present.…
Wiktor-99 Nov 7, 2024
a8bc556
Merge branch 'master' into gpio_controllers
christophfroehlich Nov 11, 2024
9c30814
Update pkg xmls
Wiktor-99 Nov 16, 2024
39d885a
Add control_msgs to CMakeLists
Wiktor-99 Nov 16, 2024
305ab61
Use DynamicInterfaceGroupValues instead of DynamicInterfaceValues
Wiktor-99 Nov 16, 2024
2f49765
Merge branch 'master' into gpio_controllers
christophfroehlich Nov 17, 2024
5c32a72
Add gpio_controllers to the release_notes and add minor fixes to the …
Wiktor-99 Nov 18, 2024
4cd5772
Update compile flags
christophfroehlich Nov 18, 2024
6ef4023
Fix format
christophfroehlich Nov 18, 2024
bc3eb30
Merge branch 'master' into gpio_controllers
christophfroehlich Nov 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/controllers_index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ The controllers are using `common hardware interface definitions`_, and may use
PID Controller <../pid_controller/doc/userdoc.rst>
Position Controllers <../position_controllers/doc/userdoc.rst>
Velocity Controllers <../velocity_controllers/doc/userdoc.rst>
Gpio Command Controller <../gpio_controllers/doc/userdoc.rst>


Broadcasters
Expand Down
4 changes: 4 additions & 0 deletions doc/release_notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,7 @@ steering_controllers_library
tricycle_controller
************************
* tricycle_controller now uses generate_parameter_library (`#957 <https://github.com/ros-controls/ros2_controllers/pull/957>`_).

gpio_controllers
************************
* The GPIO command controller was added 🎉 (`#1251 <https://github.com/ros-controls/ros2_controllers/pull/1251>`_).
115 changes: 115 additions & 0 deletions gpio_controllers/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
cmake_minimum_required(VERSION 3.8)
project(gpio_controllers)

# Default to C++14
if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 14)
endif()

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic -Werror=conversion -Werror=unused-but-set-variable
-Werror=return-type -Werror=shadow -Werror=format -Werror=range-loop-construct
-Werror=missing-braces)
endif()

# find dependencies
find_package(ament_cmake REQUIRED)
find_package(controller_interface REQUIRED)
find_package(hardware_interface REQUIRED)
find_package(pluginlib REQUIRED)
find_package(rclcpp REQUIRED)
find_package(rclcpp_lifecycle REQUIRED)
find_package(realtime_tools REQUIRED)
find_package(generate_parameter_library REQUIRED)
find_package(control_msgs REQUIRED)


generate_parameter_library(gpio_command_controller_parameters
src/gpio_command_controller_parameters.yaml
)

add_library(gpio_controllers
SHARED
src/gpio_command_controller.cpp
)
target_include_directories(gpio_controllers PRIVATE include)
target_link_libraries(gpio_controllers PUBLIC gpio_command_controller_parameters)
ament_target_dependencies(gpio_controllers PUBLIC
builtin_interfaces
controller_interface
hardware_interface
pluginlib
rclcpp_lifecycle
rcutils
realtime_tools
control_msgs
)
# Causes the visibility macros to use dllexport rather than dllimport,
# which is appropriate when building the dll but not consuming it.
target_compile_definitions(gpio_controllers PRIVATE "GPIO_COMMAND_CONTROLLER_BUILDING_DLL")
pluginlib_export_plugin_description_file(controller_interface gpio_controllers_plugin.xml)

install(
DIRECTORY include/
DESTINATION include
)

install(
TARGETS
gpio_controllers
RUNTIME DESTINATION bin
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
)

if(BUILD_TESTING)
find_package(ament_cmake_gmock REQUIRED)
find_package(controller_manager REQUIRED)
find_package(hardware_interface REQUIRED)
find_package(ros2_control_test_assets REQUIRED)

ament_add_gmock(
test_load_gpio_command_controller
test/test_load_gpio_command_controller.cpp
)

target_include_directories(test_load_gpio_command_controller PRIVATE include)
ament_target_dependencies(test_load_gpio_command_controller
controller_manager
hardware_interface
ros2_control_test_assets
)

ament_add_gmock(
test_gpio_command_controller
test/test_gpio_command_controller.cpp
)
target_include_directories(test_gpio_command_controller PRIVATE include)
target_link_libraries(test_gpio_command_controller
gpio_controllers
)
ament_target_dependencies(test_gpio_command_controller
controller_interface
hardware_interface
rclcpp
rclcpp_lifecycle
realtime_tools
ros2_control_test_assets
control_msgs
)
endif()

ament_export_dependencies(
controller_interface
hardware_interface
rclcpp
rclcpp_lifecycle
realtime_tools
)
ament_export_include_directories(
include
)
ament_export_libraries(
gpio_controllers
)
ament_package()
57 changes: 57 additions & 0 deletions gpio_controllers/doc/userdoc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
.. _gpio_controllers_userdoc:

gpio_controllers
=====================

This is a collection of controllers for hardware interfaces of type GPIO (``<gpio>`` tag in the URDF).
christophfroehlich marked this conversation as resolved.
Show resolved Hide resolved

gpio_command_controller
-----------------------------
gpio_command_controller let the user expose command interfaces of given GPIO interfaces and publishes state interfaces of the configured command interfaces.

Description of controller's interfaces
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- ``/<controller_name>/gpio_states`` [``control_msgs/msg/DynamicJointState``]: Publishes all state interfaces of the given GPIO interfaces.
- ``/<controller_name>/commands`` [``control_msgs/msg/DynamicJointState``]: A subscriber for configured command interfaces.


Parameters
^^^^^^^^^^^^^^^^^^^^^^^^

This controller uses the `generate_parameter_library <https://github.com/PickNikRobotics/generate_parameter_library>`_ to handle its parameters. The parameter `definition file located in the src folder <https://github.com/ros-controls/ros2_controllers/blob/{REPOS_FILE_BRANCH}/gpio_controllers/src/gpio_command_controller_parameters.yaml>`_ contains descriptions for all the parameters used by the controller.

.. generate_parameter_library_details::
../src/gpio_command_controller_parameters.yaml

The controller expects at least one GPIO interface and the corresponding command interface names or state interface. However, these Command and State interfaces are optional. The controller behaves as a broadcaster when no Command Interface is present, thereby publishing the configured GPIO state interfaces if set, else the one present in the URDF.

.. note::

When no state interface is provided in the param file, the controller will try to use state_interfaces from ros2_control's config placed in the URDF for configured gpio interfaces.
However, command interfaces will not be configured based on the available URDF setup.

.. code-block:: yaml

gpio_command_controller:
ros__parameters:
type: gpio_controllers/GpioCommandController
gpios:
- Gpio1
- Gpio2
command_interfaces:
Gpio1:
- interfaces:
- dig.1
- dig.2
- dig.3
Gpio2:
- interfaces:
- ana.1
- ana.2
state_interfaces:
Gpio2:
- interfaces:
- ana.1
- ana.2

With the above-defined controller configuration, the controller will accept commands for all gpios' interfaces and will only publish the state of Gpio2.
7 changes: 7 additions & 0 deletions gpio_controllers/gpio_controllers_plugin.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<library path="gpio_controllers">
<class name="gpio_controllers/GpioCommandController" type="gpio_controllers::GpioCommandController" base_class_type="controller_interface::ControllerInterface">
<description>
The gpio command controller commands a group of gpios using multiple interfaces.
</description>
</class>
</library>
114 changes: 114 additions & 0 deletions gpio_controllers/include/gpio_controllers/gpio_command_controller.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// Copyright 2022 ICUBE Laboratory, University of Strasbourg
//
// 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 GPIO_CONTROLLERS__GPIO_COMMAND_CONTROLLER_HPP_
#define GPIO_CONTROLLERS__GPIO_COMMAND_CONTROLLER_HPP_

#include <memory>
#include <string>
#include <unordered_map>
#include <vector>

#include "control_msgs/msg/dynamic_interface_group_values.hpp"
#include "controller_interface/controller_interface.hpp"
#include "gpio_command_controller_parameters.hpp"
#include "gpio_controllers/visibility_control.h"
#include "rclcpp_lifecycle/node_interfaces/lifecycle_node_interface.hpp"
#include "rclcpp_lifecycle/state.hpp"
#include "realtime_tools/realtime_buffer.h"
#include "realtime_tools/realtime_publisher.h"

namespace gpio_controllers
{
using CmdType = control_msgs::msg::DynamicInterfaceGroupValues;
using StateType = control_msgs::msg::DynamicInterfaceGroupValues;
using CallbackReturn = controller_interface::CallbackReturn;
using InterfacesNames = std::vector<std::string>;
using MapOfReferencesToCommandInterfaces = std::unordered_map<
std::string, std::reference_wrapper<hardware_interface::LoanedCommandInterface>>;
using MapOfReferencesToStateInterfaces =
std::unordered_map<std::string, std::reference_wrapper<hardware_interface::LoanedStateInterface>>;
using StateInterfaces =
std::vector<std::reference_wrapper<hardware_interface::LoanedStateInterface>>;

class GpioCommandController : public controller_interface::ControllerInterface
{
public:
GPIO_COMMAND_CONTROLLER_PUBLIC
GpioCommandController();

GPIO_COMMAND_CONTROLLER_PUBLIC
controller_interface::InterfaceConfiguration command_interface_configuration() const override;

GPIO_COMMAND_CONTROLLER_PUBLIC
controller_interface::InterfaceConfiguration state_interface_configuration() const override;

GPIO_COMMAND_CONTROLLER_PUBLIC
CallbackReturn on_init() override;

GPIO_COMMAND_CONTROLLER_PUBLIC
CallbackReturn on_configure(const rclcpp_lifecycle::State & previous_state) override;

GPIO_COMMAND_CONTROLLER_PUBLIC
CallbackReturn on_activate(const rclcpp_lifecycle::State & previous_state) override;

GPIO_COMMAND_CONTROLLER_PUBLIC
CallbackReturn on_deactivate(const rclcpp_lifecycle::State & previous_state) override;

GPIO_COMMAND_CONTROLLER_PUBLIC
controller_interface::return_type update(
const rclcpp::Time & time, const rclcpp::Duration & period) override;

private:
void store_command_interface_types();
void store_state_interface_types();
void initialize_gpio_state_msg();
void update_gpios_states();
controller_interface::return_type update_gpios_commands();
template <typename T>
std::unordered_map<std::string, std::reference_wrapper<T>> create_map_of_references_to_interfaces(
const InterfacesNames & interfaces_from_params, std::vector<T> & configured_interfaces);
template <typename T>
bool check_if_configured_interfaces_matches_received(
const InterfacesNames & interfaces_from_params, const T & configured_interfaces);
void apply_state_value(
StateType & state_msg, std::size_t gpio_index, std::size_t interface_index) const;
void apply_command(
const CmdType & gpio_commands, std::size_t gpio_index,
std::size_t command_interface_index) const;
bool should_broadcast_all_interfaces_of_configured_gpios() const;
void set_all_state_interfaces_of_configured_gpios();
InterfacesNames get_gpios_state_interfaces_names(const std::string & gpio_name) const;
bool update_dynamic_map_parameters();
std::vector<hardware_interface::ComponentInfo> get_gpios_from_urdf() const;

protected:
InterfacesNames command_interface_types_;
InterfacesNames state_interface_types_;
MapOfReferencesToCommandInterfaces command_interfaces_map_;
MapOfReferencesToStateInterfaces state_interfaces_map_;

realtime_tools::RealtimeBuffer<std::shared_ptr<CmdType>> rt_command_ptr_{};
rclcpp::Subscription<CmdType>::SharedPtr gpios_command_subscriber_{};

std::shared_ptr<rclcpp::Publisher<StateType>> gpio_state_publisher_{};
std::shared_ptr<realtime_tools::RealtimePublisher<StateType>> realtime_gpio_state_publisher_{};

std::shared_ptr<gpio_command_controller_parameters::ParamListener> param_listener_{};
gpio_command_controller_parameters::Params params_;
};

} // namespace gpio_controllers

#endif // GPIO_CONTROLLERS__GPIO_COMMAND_CONTROLLER_HPP_
49 changes: 49 additions & 0 deletions gpio_controllers/include/gpio_controllers/visibility_control.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright 2022 ICUBE Laboratory, University of Strasbourg
//
// 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 GPIO_CONTROLLERS__VISIBILITY_CONTROL_H_
#define GPIO_CONTROLLERS__VISIBILITY_CONTROL_H_

// This logic was borrowed (then namespaced) from the examples on the gcc wiki:
// https://gcc.gnu.org/wiki/Visibility

#if defined _WIN32 || defined __CYGWIN__
#ifdef __GNUC__
#define GPIO_COMMAND_CONTROLLER_EXPORT __attribute__((dllexport))
#define GPIO_COMMAND_CONTROLLER_IMPORT __attribute__((dllimport))
#else
#define GPIO_COMMAND_CONTROLLER_EXPORT __declspec(dllexport)
#define GPIO_COMMAND_CONTROLLER_IMPORT __declspec(dllimport)
#endif
#ifdef GPIO_COMMAND_CONTROLLER_BUILDING_LIBRARY
#define GPIO_COMMAND_CONTROLLER_PUBLIC GPIO_COMMAND_CONTROLLER_EXPORT
#else
#define GPIO_COMMAND_CONTROLLER_PUBLIC GPIO_COMMAND_CONTROLLER_IMPORT
#endif
#define GPIO_COMMAND_CONTROLLER_PUBLIC_TYPE GPIO_COMMAND_CONTROLLER_PUBLIC
#define GPIO_COMMAND_CONTROLLER_LOCAL
#else
#define GPIO_COMMAND_CONTROLLER_EXPORT __attribute__((visibility("default")))
#define GPIO_COMMAND_CONTROLLER_IMPORT
#if __GNUC__ >= 4
#define GPIO_COMMAND_CONTROLLER_PUBLIC __attribute__((visibility("default")))
#define GPIO_COMMAND_CONTROLLER_LOCAL __attribute__((visibility("hidden")))
#else
#define GPIO_COMMAND_CONTROLLER_PUBLIC
#define GPIO_COMMAND_CONTROLLER_LOCAL
#endif
#define GPIO_COMMAND_CONTROLLER_PUBLIC_TYPE
#endif

#endif // GPIO_CONTROLLERS__VISIBILITY_CONTROL_H_
30 changes: 30 additions & 0 deletions gpio_controllers/package.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>gpio_controllers</name>
<version>4.15.0</version>
<description>Controllers to interact with gpios.</description>
<maintainer email="[email protected]">Maciej Bednarczyk</maintainer>
<maintainer email="[email protected]">Wiktor Bajor</maintainer>
<license>Apache License 2.0</license>

<buildtool_depend>ament_cmake</buildtool_depend>

<depend>controller_interface</depend>
<depend>hardware_interface</depend>
<depend>rclcpp</depend>
<depend>rclcpp_lifecycle</depend>
<depend>control_msgs</depend>
<depend>realtime_tools</depend>
<depend>generate_parameter_library</depend>

<build_depend>pluginlib</build_depend>

<test_depend>ament_cmake_gmock</test_depend>
<test_depend>controller_manager</test_depend>
<test_depend>ros2_control_test_assets</test_depend>

<export>
<build_type>ament_cmake</build_type>
</export>
</package>
Loading
Loading