-
Notifications
You must be signed in to change notification settings - Fork 424
Added Swerve Drive Controller Package #1694
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
base: master
Are you sure you want to change the base?
Added Swerve Drive Controller Package #1694
Conversation
christophfroehlich
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks again for your contribution. Could you please fix the failing tests? A very quick first review below.
Do you mind add a brief section in the kinematics section of the docs, even in a new PR to get it merged faster? Thanks!
swerve_drive_controller/include/swerve_drive_controller/swerve_drive_controller.hpp
Outdated
Show resolved
Hide resolved
swerve_drive_controller/include/swerve_drive_controller/swerve_drive_kinematics.hpp
Outdated
Show resolved
Hide resolved
|
I'll make changes and push. |
…s.txt of swerve_drive_controller package Signed-off-by: nitin <nitinmaurya2606@gmail.com>
|
do you mind cherry-picking the changes to the docs in a separate PR? Splitting this up would help to reviewing things. |
I have raised a separate PR for changes in docs. PR #1712 |
Maverobot
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi there, thanks for your contribution! I've started reviewing the changes and have left a few comments. I will try to find time to work through it and will follow up once I'm done.
swerve_drive_controller/include/swerve_drive_controller/swerve_drive_controller.hpp
Outdated
Show resolved
Hide resolved
swerve_drive_controller/include/swerve_drive_controller/swerve_drive_controller.hpp
Outdated
Show resolved
Hide resolved
swerve_drive_controller/include/swerve_drive_controller/swerve_drive_controller.hpp
Outdated
Show resolved
Hide resolved
Co-authored-by: Zheng Qu <quzhengrobot@gmail.com>
|
This pull request is in conflict. Could you fix it @nitin2606? |
Signed-off-by: nitin <nitinmaurya2606@gmail.com>
|
There's another issue: the |
userdoc.rst is not updated. All the controllers of ros2_control have switched to TwistStamped only. |
computed from wheelbase, trackwidth, offset_x, and offset_y. This improves flexibility and reduces duplication when changing robot dimensions. Signed-off-by: nitin <nitinmaurya2606@gmail.com>
Narukara
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if this is the right place to handle the wheel radius. I tested the modified controller using gazebo, and both the controls and odometry seem to work fine. By the way, I used the humble version, so I made some necessary changes.
| auto logger = get_node()->get_logger(); | ||
|
|
||
| RCLCPP_INFO(logger, "Updated Kinematics"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| auto logger = get_node()->get_logger(); | |
| RCLCPP_INFO(logger, "Updated Kinematics"); |
The controller prints a lot of this when it runs, which is a bit annoying.
| wheel_joint_names[i]); | ||
| } | ||
| axle_handles_[i]->set_position(wheel_command[i].steering_angle); | ||
| wheel_handles_[i]->set_velocity(wheel_command[i].drive_velocity); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| wheel_handles_[i]->set_velocity(wheel_command[i].drive_velocity); | |
| wheel_handles_[i]->set_velocity(wheel_command[i].drive_velocity / params_.wheel_radius); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Solved in latest commit
| } | ||
| else | ||
| { | ||
| velocity_array[i] = wheel_handles_[i]->get_feedback(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| velocity_array[i] = wheel_handles_[i]->get_feedback(); | |
| velocity_array[i] = wheel_handles_[i]->get_feedback() * params_.wheel_radius; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Solved in latest commit
|
Another small issue: I found that when I stop sending speed commands, the controller automatically straightens all the wheels. Maybe it would be more reasonable to keep each wheel at its current steering angle? |
- Updated kinematics to compute angular velocity for wheels instead of linear velocity for more accurate motion control. - Enhanced controller to retain the last steering angle when stopped, preventing the wheels from snapping back to zero orientation.
please check latest commit |
| if (realtime_odometry_publisher_) | ||
| { | ||
| auto & odometry_message = realtime_odometry_publisher_->msg_; | ||
| odometry_message.header.stamp = time; | ||
| odometry_message.pose.pose.position.x = odometry_.x; | ||
| odometry_message.pose.pose.position.y = odometry_.y; | ||
| odometry_message.pose.pose.orientation.x = orientation.x(); | ||
| odometry_message.pose.pose.orientation.y = orientation.y(); | ||
| odometry_message.pose.pose.orientation.z = orientation.z(); | ||
| odometry_message.pose.pose.orientation.w = orientation.w(); | ||
| realtime_odometry_publisher_->tryPublish(odometry_message); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The odometry message published here does not contain twist information (twist.linear.x, twist.linear.y, twist.angular.z). I have confirmed this issue in the Gazebo test.
Narukara
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add odometry twist
swerve_drive_controller/include/swerve_drive_controller/swerve_drive_kinematics.hpp
Show resolved
Hide resolved
…_drive_kinematics.hpp Co-authored-by: Narukara <narukara17@gmail.com>
Co-authored-by: Narukara <narukara17@gmail.com>
Co-authored-by: Narukara <narukara17@gmail.com>
Co-authored-by: Narukara <narukara17@gmail.com>
Signed-off-by: nitin <nitinmaurya2606@gmail.com>
Signed-off-by: nitin <nitinmaurya2606@gmail.com>
|
I've found another tricky problem. When I send the command 2025.10.14.15.21.35.webm |
This appears to be a kinematics issue — when the robot is commanded to move backward, the wheels shouldn’t rotate; they should simply translate backward. |
This is a "feature" of the solution of the inverse kinematics not being unique. But this could be handled to have a best effort behavior. Having a look a the video, there should also be some master-slave behavior of the steering and speed command of the wheels be employed, see the |
Signed-off-by: nitin <nitinmaurya2606@gmail.com>
Please check the latest commit, I have tried to fix the issue |
Yes, that should be considered a feature. In my controller (which is not implemented using the 'ros2_control' framework, just normal node), I enforce steering angle limits of ±π/2. When the inverse kinematics produces an angle outside these limits, I simply add π to the steering angle and reverse the wheel’s driving direction. In the video case, this means the robot would just reverse the direction of the driving wheel. I’ve also seen some real-world implementations where, if the steering angle change is larger than a certain threshold, the driving wheels wait until the steering angle is reached—effectively introducing a short delay, similar to dead time in control system theory. However, this can become a “problem” if the path contains discontinuities or sharp turns. To avoid this, it is often better to generate smoother, polynomial-based paths that ensure continuous steering without large jumps. |
|
The
I'm unsure how this applies to a four-wheel independent steering vehicle. In the vehicle model I'm using (which works correctly), the steering mechanism is defined as follows: <!-- steer macro -->
<xacro:macro name="steer" params="name x y z">
<link name="${name}">
<inertial>
<mass value="0.0001"/>
<inertia ixx="0.000001" ixy="0.0" ixz="0.0" iyy="0.000001" iyz="0.0" izz="0.000001" />
</inertial>
</link>
<joint name="${name}_joint" type="continuous">
<origin xyz="${x} ${y} ${z}" rpy="0 0 0" />
<parent link="chassis" />
<child link="${name}" />
<axis xyz="0 0 1" />
<dynamics damping="0.0" />
</joint>
</xacro:macro>Its Z-axis points upwards, and it rotates around the Z-axis. In fact, I'm mimicking the design of the Ackerman vehicle here. |
The control of a four-wheel independent steering vehicle with steering angle limitations might be a rather complex problem. Personally, I suggest that we only complete the basic functions in this PR and leave this problem to the next issue/PR. 🙂 |
|
Thank you @Narukara for the feedback. The link to the specifications/documentation of the steering mechanism regarding the Z axis is very useful. I have a similar definition of the steering joint as yours, it's just that its parent frame Z axis points downwards 🙂 Subsequently also the steering axis points down. Given that this is an isolated issue, I understand that it does not need to make it into the PR. As for the limited rotation of the steering axes: totally agree! If it's a complex problem to solve it can be adjusted iteratively later. In this case, I would find it reasonable to note this limitation somewhere. |
|
Just wanted to mention that this PR introduced the |
Maybe not. But you can always compile the rolling version on humble distro, see "development version". |



Description
This PR introduces the swerve_drive_controller, a new controller for swerve drive robots with four independently steerable wheels, enabling omnidirectional motion in ROS 2. It complements controllers like diff_drive_controller by supporting advanced mobile robot platforms.
Features
Supports geometry_msgs/msg/Twist or TwistStamped velocity inputs (x, y linear; z angular).
Publishes raw nav_msgs/msg/Odometry for user-defined post-processing.
Publishes /tf transforms (optional, if enable_odom_tf=true).
Configurable via YAML for wheel geometry and kinematic constraints.
Changes
Added swerve_drive_controller package (src/, include/, test/).
Exported as a pluginlib plugin (swerve_drive_controller_plugin.xml).
Updated ros2_controllers CMakeLists.txt and package.xml.
Included gtest tests (test/test_swerve_drive_controller.cpp) and config (test/config/test_swerve_drive_controller.yaml).