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

Add Mecanum Drive Controller #512

Open
wants to merge 94 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
7b04ea1
compiling without error
Jan 6, 2023
f03dd05
all tests working
Jan 6, 2023
c5e26db
reorganized publishers added code to print values for debug
Jan 7, 2023
2fc904d
added meaning full param values
Jan 8, 2023
fd91be7
next line in comment
Jan 8, 2023
99413af
Automated formatting files.
destogl Jan 9, 2023
149c39a
Manual changes of formatting.
destogl Jan 9, 2023
c55911b
Delete LICENSE
destogl Jan 9, 2023
2a87584
Apply suggestions from code review
Robotgir Jan 10, 2023
13e1c7a
Apply suggestions from code review
Robotgir Jan 10, 2023
9dc99d3
used the suggested structure
Jan 10, 2023
02b08cf
general changes
Jan 10, 2023
e7247bd
removed bacc accumulators
Jan 10, 2023
1268588
renaming to more meaningful and readable variable names
Jan 11, 2023
92a755d
code review suggestions implementing
Jan 11, 2023
62663d8
Apply suggestions from code review
Robotgir Jan 11, 2023
e130765
added description
Jan 11, 2023
179a84e
checked more values against the behavior of controller methods
Jan 11, 2023
826f8ae
changed controller type to CtrlType
Jan 11, 2023
14bcf33
Update mecanum_drive_controller/test/test_mecanum_drive_controller.cpp
destogl Jan 11, 2023
a637de4
updated cmakelists structure
Jan 12, 2023
9ca0a50
renaming variables
Jan 12, 2023
56e5817
changed description
Jan 12, 2023
4962c0a
resetting msg if msg is valid after receiving a to old msg
Jan 13, 2023
0c9eb02
estructuring parameters in yaml
Jan 13, 2023
56e8e2f
comparing float values
Jan 13, 2023
3a59aef
Apply suggestions from code review
Robotgir Jan 13, 2023
b6d1f51
added description for each test as comment
Jan 13, 2023
8624f72
added preceding controller tests
Jan 14, 2023
38a3500
reorganized reference_interfaces configuration method
Jan 14, 2023
08f2f2d
configuration of interfaces in loop
Jan 14, 2023
2e52fd3
final fixups
Jan 14, 2023
3d437bf
using control_msgs::msg::MecanumDriveControllerState and removing cus…
Jan 16, 2023
1090a3a
using control_msgs::msg::MecanumDriveControllerState and removing cus…
Jan 16, 2023
0f3aef4
added chained mode test for update logic
Jan 16, 2023
72a3d72
changed wheel vl names to more descriptive
Jan 16, 2023
1d0562f
renamed rot and traslation matrix variable names
Jan 16, 2023
16b086f
renamed vl variable to more descriptive
Jan 16, 2023
5650ad9
ran pre-commit formatter
Jan 16, 2023
6cae0d2
set ref_itfces to 0 to stop vehicle in case of timeout
Jan 16, 2023
37f9d10
added description
Jan 18, 2023
f0a3736
check nan
Jan 19, 2023
7dc9a60
odom vel naming descriptive
Jan 24, 2023
0405b9b
removed outdated nomenclature
Jan 24, 2023
2aa089c
add comment
Jan 24, 2023
c6c9c97
Apply suggestions from code review
destogl Jan 27, 2023
0e4879a
Update mecanum_drive_controller/src/mecanum_drive_controller.cpp
destogl Jan 27, 2023
619118c
Update mecanum_drive_controller/src/mecanum_drive_controller.cpp
destogl Jan 27, 2023
c26cb64
Update .pre-commit-config.yaml
destogl Jan 27, 2023
2803602
Update package.xml
destogl Jan 27, 2023
6897de8
removing boost
Jan 30, 2023
ef205a2
removing unused variable
Jan 30, 2023
9cd3d11
addressing warnings
Jan 30, 2023
f9fdf30
update cmake version
Jan 30, 2023
b73cf7b
renaming wheels_k to more descriptive naming sum_of_robot_center_proj…
Jan 30, 2023
8b92a47
renames joint_names to command_joint_names
Jan 30, 2023
0d363ea
removing unused variable
Jan 30, 2023
20c91bb
pre-commit clang format 14
Jan 30, 2023
0a6a204
updating test logic w.r.t reset ref_interfaces
Jan 30, 2023
7764291
added changes w.r.t control_msgs update
Jan 30, 2023
a1a288d
cpp_lint check for pre-comit
Jan 30, 2023
8df9f78
cpp_lint check update
Jan 30, 2023
7fc5284
handling ref_timeout==0 in update_and_write method
Jan 30, 2023
970bd1b
updated test comments with when xx then yy scheme
Jan 30, 2023
7fc7b90
Revert "handling ref_timeout==0 in update_and_write method"
Jan 30, 2023
40855bb
renaming test names to whenn xx expect yy scheme
Jan 31, 2023
23ab872
Update tests
destogl Jan 31, 2023
ec6424a
Restructure CMakeLists.txt and add docs.
destogl Feb 8, 2023
447a504
Update mecanum_drive_controller/mecanum_drive_controller.xml
destogl Feb 13, 2023
37b27d1
Update mecanum_drive_controller/package.xml
destogl Feb 13, 2023
ade56b6
Update mecanum_drive_controller.yaml
destogl Feb 13, 2023
ea9b21f
implemneted suggested changes compiling and ll tests pass
Feb 13, 2023
6077003
ran precommit
Feb 13, 2023
f00cd5e
Update mecanum_drive_controller/test/test_mecanum_drive_controller.cpp
destogl Apr 11, 2023
8e853c7
Add missing nav_msgs dependecdy
destogl Apr 11, 2023
3815bcf
Remove odometry field from status message
destogl Apr 11, 2023
5033c9d
Apply suggestions from code review
destogl Apr 11, 2023
bd3bfc0
Fix a few typos and rephrase
bmagyar May 14, 2023
f060d17
Correct controller loading test
destogl Aug 28, 2023
0a5e563
Update mecanum_drive_controller/src/odometry.cpp
destogl Aug 28, 2023
bc87e31
Update docs with note about odometry calculation.
destogl Aug 28, 2023
93d1bf1
Update mecanum_drive_controller/src/mecanum_drive_controller.yaml
destogl Aug 28, 2023
b2605a1
Fix mixing of joints and fix to velocity only interface.
destogl Jun 17, 2024
50cd77c
Fix formatting and typos.
destogl Jun 17, 2024
98b1e59
Update mecanum_drive_controller/src/mecanum_drive_controller.yaml
destogl Jun 19, 2024
a34c665
Update the use explict parameters for the wheels.
destogl Jun 19, 2024
3da18a8
Update .pre-commit-config.yaml
destogl Jun 27, 2024
1f58f8d
Fix ordering of wheels to be correct.
destogl Jul 2, 2024
4852699
Update mecanum_drive_controller/doc/userdoc.rst
destogl Jul 3, 2024
57fac95
Odometry Position Frame (#21)
luis-camero Jul 31, 2024
41596c4
Merge branch 'master' into add-mecanum-drive-controller
destogl Jul 31, 2024
14277e4
Merge branch 'master' into add-mecanum-drive-controller
destogl Aug 14, 2024
355fae3
Fix mecanum (#23)
christophfroehlich Aug 21, 2024
407aca9
Merge branch 'master' into add-mecanum-drive-controller
bmagyar Sep 11, 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 @@ -28,6 +28,7 @@ Controllers for Wheeled Mobile Robots
:titlesonly:

Differential Drive Controller <../diff_drive_controller/doc/userdoc.rst>
Mecanum Drive Controllers <../mecanum_drive_controller/doc/userdoc.rst>
Steering Controllers Library <../steering_controllers_library/doc/userdoc.rst>
Tricycle Controller <../tricycle_controller/doc/userdoc.rst>

Expand Down
108 changes: 108 additions & 0 deletions mecanum_drive_controller/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
cmake_minimum_required(VERSION 3.16)
project(mecanum_drive_controller LANGUAGES CXX)

if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# find dependencies
set(THIS_PACKAGE_INCLUDE_DEPENDS
controller_interface
hardware_interface
generate_parameter_library
nav_msgs
pluginlib
destogl marked this conversation as resolved.
Show resolved Hide resolved
rclcpp
rclcpp_lifecycle
realtime_tools
std_srvs
tf2
tf2_geometry_msgs
tf2_msgs
)

find_package(ament_cmake REQUIRED)
find_package(backward_ros REQUIRED)
foreach(Dependency IN ITEMS ${THIS_PACKAGE_INCLUDE_DEPENDS})
find_package(${Dependency} REQUIRED)
endforeach()

generate_parameter_library(mecanum_drive_controller_parameters
src/mecanum_drive_controller.yaml
)

add_library(
mecanum_drive_controller
SHARED
src/mecanum_drive_controller.cpp
src/odometry.cpp
)
target_compile_features(mecanum_drive_controller PUBLIC cxx_std_17)
target_include_directories(mecanum_drive_controller PUBLIC
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:include/${PROJECT_NAME}>")
target_link_libraries(mecanum_drive_controller PUBLIC
mecanum_drive_controller_parameters)
ament_target_dependencies(mecanum_drive_controller PUBLIC ${THIS_PACKAGE_INCLUDE_DEPENDS})

# Causes the visibility macros to use dllexport rather than dllimport,
# which is appropriate when building the dll but not consuming it.
target_compile_definitions(mecanum_drive_controller PRIVATE "ACKERMANN_STEERING_CONTROLLER_BUILDING_DLL")

pluginlib_export_plugin_description_file(
controller_interface mecanum_drive_controller.xml)

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)

add_rostest_with_parameters_gmock(test_load_mecanum_drive_controller
test/test_load_mecanum_drive_controller.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test/mecanum_drive_controller_params.yaml
)
ament_target_dependencies(test_load_mecanum_drive_controller
controller_manager
ros2_control_test_assets
)

add_rostest_with_parameters_gmock(
test_mecanum_drive_controller test/test_mecanum_drive_controller.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test/mecanum_drive_controller_params.yaml)
target_include_directories(test_mecanum_drive_controller PRIVATE include)
target_link_libraries(test_mecanum_drive_controller mecanum_drive_controller)
ament_target_dependencies(
test_mecanum_drive_controller
controller_interface
hardware_interface
)

add_rostest_with_parameters_gmock(
test_mecanum_drive_controller_preceeding test/test_mecanum_drive_controller_preceeding.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test/mecanum_drive_controller_preceeding_params.yaml)
target_include_directories(test_mecanum_drive_controller_preceeding PRIVATE include)
target_link_libraries(test_mecanum_drive_controller_preceeding mecanum_drive_controller)
ament_target_dependencies(
test_mecanum_drive_controller_preceeding
controller_interface
hardware_interface
)
endif()

install(
DIRECTORY include/
DESTINATION include/mecanum_drive_controller
)

install(
TARGETS mecanum_drive_controller mecanum_drive_controller_parameters
EXPORT export_mecanum_drive_controller
RUNTIME DESTINATION bin
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
)

ament_export_targets(export_mecanum_drive_controller HAS_LIBRARY_TARGET)
ament_export_dependencies(${THIS_PACKAGE_INCLUDE_DEPENDS})
ament_package()
61 changes: 61 additions & 0 deletions mecanum_drive_controller/doc/userdoc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
.. _mecanum_drive_controller_userdoc:

mecanum_drive_controller
=========================

Library with shared functionalities for mobile robot controllers with mecanum drive (four wheels).
The library implements generic odometry and update methods and defines the main interfaces.

Execution logic of the controller
----------------------------------

The controller uses velocity input, i.e., stamped Twist messages where linear ``x``, ``y``, and angular ``z`` components are used.
Values in other components are ignored.
In the chain mode, the controller provides three reference interfaces, one for linear velocity and one for steering angle position.
Other relevant features are:

- odometry publishing as Odometry and TF message;
- input command timeout based on a parameter.

Note about odometry calculation:
In the DiffDRiveController, the velocity is filtered out, but we prefer to return it raw and let the user perform post-processing at will.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
In the DiffDRiveController, the velocity is filtered out, but we prefer to return it raw and let the user perform post-processing at will.
In the diff_drive_controller, the velocity is filtered out, but we prefer to return it raw and let the user perform post-processing at will.

We prefer this way of doing so as filtering introduces delay (which makes it difficult to interpret and compare behavior curves).


Description of controller's interfaces
--------------------------------------

References (from a preceding controller)
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
- <reference_names[i]>/<interface_name> [double] # in [rad] or [rad/s]

Commands
,,,,,,,,,
- <command_joint_names[i]>/<interface_name> [double] # in [rad] or [rad/s]

States
,,,,,,,
- <joint_names[i]>/<interface_name> [double] # in [rad] or [rad/s]
..note ::

``joint_names[i]`` can be of ``state_joint_names`` parameter (if used), ``command_joint_names`` otherwise.


Subscribers
,,,,,,,,,,,,
Used when the controller is not in chained mode (``in_chained_mode == false``).

- <controller_name>/reference [geometry_msgs/msg/TwistStamped]

Publishers
,,,,,,,,,,,
- <controller_name>/odometry [nav_msgs/msg/Odometry]
- <controller_name>/tf_odometry [tf2_msgs/msg/TFMessage]
- <controller_name>/controller_state [control_msgs/msg/MecanumDriveControllerState]

Parameters
,,,,,,,,,,,

For a list of parameters and their meaning, see the YAML file in the ``src`` folder of the controller's package.

For an exemplary parameterization, see the ``test`` folder of the controller's package.
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt)
//
// 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 MECANUM_DRIVE_CONTROLLER__MECANUM_DRIVE_CONTROLLER_HPP_
#define MECANUM_DRIVE_CONTROLLER__MECANUM_DRIVE_CONTROLLER_HPP_

#include <chrono>
#include <cmath>
#include <memory>
#include <queue>
#include <string>
#include <utility>
#include <vector>

#include "controller_interface/chainable_controller_interface.hpp"
#include "mecanum_drive_controller/odometry.hpp"
#include "mecanum_drive_controller/visibility_control.h"
#include "mecanum_drive_controller_parameters.hpp"
#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"
#include "std_srvs/srv/set_bool.hpp"

#include "control_msgs/msg/mecanum_drive_controller_state.hpp"
#include "geometry_msgs/msg/twist_stamped.hpp"
#include "nav_msgs/msg/odometry.hpp"
#include "tf2_msgs/msg/tf_message.hpp"
namespace mecanum_drive_controller
{
// name constants for state interfaces
static constexpr size_t NR_STATE_ITFS = 4;

// name constants for command interfaces
static constexpr size_t NR_CMD_ITFS = 4;

// name constants for reference interfaces
static constexpr size_t NR_REF_ITFS = 3;

class MecanumDriveController : public controller_interface::ChainableControllerInterface
{
public:
MECANUM_DRIVE_CONTROLLER__VISIBILITY_PUBLIC
MecanumDriveController();

MECANUM_DRIVE_CONTROLLER__VISIBILITY_PUBLIC
controller_interface::CallbackReturn on_init() override;

MECANUM_DRIVE_CONTROLLER__VISIBILITY_PUBLIC
controller_interface::InterfaceConfiguration command_interface_configuration() const override;

MECANUM_DRIVE_CONTROLLER__VISIBILITY_PUBLIC
controller_interface::InterfaceConfiguration state_interface_configuration() const override;

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

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

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

MECANUM_DRIVE_CONTROLLER__VISIBILITY_PUBLIC
controller_interface::return_type update_reference_from_subscribers(
const rclcpp::Time & time, const rclcpp::Duration & period) override;

MECANUM_DRIVE_CONTROLLER__VISIBILITY_PUBLIC
controller_interface::return_type update_and_write_commands(
const rclcpp::Time & time, const rclcpp::Duration & period) override;

using ControllerReferenceMsg = geometry_msgs::msg::TwistStamped;
using OdomStateMsg = nav_msgs::msg::Odometry;
using TfStateMsg = tf2_msgs::msg::TFMessage;
using ControllerStateMsg = control_msgs::msg::MecanumDriveControllerState;

protected:
std::shared_ptr<mecanum_drive_controller::ParamListener> param_listener_;
mecanum_drive_controller::Params params_;

/**
* The list is sorted in the following order:
* - front left wheel
* - front right wheel
* - back right wheel
* - back left wheel
*/
enum WheelIndex : std::size_t
{
FRONT_LEFT = 0,
FRONT_RIGHT = 1,
REAR_RIGHT = 2,
REAR_LEFT = 3
};

/// Internal lists with joint names.
/**
* Internal lists with joint names sorted as in `WheelIndex` enum.
*/
std::vector<std::string> command_joint_names_;

/// Internal lists with joint names.
/**
* Internal lists with joint names sorted as in `WheelIndex` enum.
* If parameters for state joint names are *not* defined, this list is the same as
* `command_joint_names_`.
*/
std::vector<std::string> state_joint_names_;

// Names of the references, ex: high level vel commands from MoveIt, Nav2, etc.
// used for preceding controller
std::vector<std::string> reference_names_;

// Command subscribers and Controller State, odom state, tf state publishers
rclcpp::Subscription<ControllerReferenceMsg>::SharedPtr ref_subscriber_ = nullptr;
realtime_tools::RealtimeBuffer<std::shared_ptr<ControllerReferenceMsg>> input_ref_;
rclcpp::Duration ref_timeout_ = rclcpp::Duration::from_seconds(0.0);

using OdomStatePublisher = realtime_tools::RealtimePublisher<OdomStateMsg>;
rclcpp::Publisher<OdomStateMsg>::SharedPtr odom_s_publisher_;
std::unique_ptr<OdomStatePublisher> rt_odom_state_publisher_;

using TfStatePublisher = realtime_tools::RealtimePublisher<TfStateMsg>;
rclcpp::Publisher<TfStateMsg>::SharedPtr tf_odom_s_publisher_;
std::unique_ptr<TfStatePublisher> rt_tf_odom_state_publisher_;

using ControllerStatePublisher = realtime_tools::RealtimePublisher<ControllerStateMsg>;
rclcpp::Publisher<ControllerStateMsg>::SharedPtr controller_s_publisher_;
std::unique_ptr<ControllerStatePublisher> controller_state_publisher_;

// override methods from ChainableControllerInterface
std::vector<hardware_interface::CommandInterface> on_export_reference_interfaces() override;

bool on_set_chained_mode(bool chained_mode) override;

Odometry odometry_;

private:
// callback for topic interface
MECANUM_DRIVE_CONTROLLER__VISIBILITY_LOCAL
void reference_callback(const std::shared_ptr<ControllerReferenceMsg> msg);

double velocity_in_center_frame_linear_x_; // [m/s]
double velocity_in_center_frame_linear_y_; // [m/s]
double velocity_in_center_frame_angular_z_; // [rad/s]
};

} // namespace mecanum_drive_controller

#endif // MECANUM_DRIVE_CONTROLLER__MECANUM_DRIVE_CONTROLLER_HPP_
Loading
Loading