-
Notifications
You must be signed in to change notification settings - Fork 389
Add velocity feedback option for diff_drive_controller #260
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
Changes from all commits
bc62802
81f35b0
3a14e7b
cdec993
8a005bb
93c77b7
2248fe3
02ce596
1a442fe
4f79852
1fdb105
dc58149
352ec3a
d31115a
a45fd43
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -48,6 +48,11 @@ using lifecycle_msgs::msg::State; | |||||
|
||||||
DiffDriveController::DiffDriveController() : controller_interface::ControllerInterface() {} | ||||||
|
||||||
const char * DiffDriveController::feedback_type() const | ||||||
{ | ||||||
return odom_params_.position_feedback ? HW_IF_POSITION : HW_IF_VELOCITY; | ||||||
} | ||||||
|
||||||
CallbackReturn DiffDriveController::on_init() | ||||||
{ | ||||||
try | ||||||
|
@@ -68,6 +73,7 @@ CallbackReturn DiffDriveController::on_init() | |||||
auto_declare<std::vector<double>>("pose_covariance_diagonal", std::vector<double>()); | ||||||
auto_declare<std::vector<double>>("twist_covariance_diagonal", std::vector<double>()); | ||||||
auto_declare<bool>("open_loop", odom_params_.open_loop); | ||||||
auto_declare<bool>("position_feedback", odom_params_.position_feedback); | ||||||
auto_declare<bool>("enable_odom_tf", odom_params_.enable_odom_tf); | ||||||
|
||||||
auto_declare<double>("cmd_vel_timeout", cmd_vel_timeout_.count() / 1000.0); | ||||||
|
@@ -123,11 +129,11 @@ InterfaceConfiguration DiffDriveController::state_interface_configuration() cons | |||||
std::vector<std::string> conf_names; | ||||||
for (const auto & joint_name : left_wheel_names_) | ||||||
{ | ||||||
conf_names.push_back(joint_name + "/" + HW_IF_POSITION); | ||||||
conf_names.push_back(joint_name + "/" + feedback_type()); | ||||||
} | ||||||
for (const auto & joint_name : right_wheel_names_) | ||||||
{ | ||||||
conf_names.push_back(joint_name + "/" + HW_IF_POSITION); | ||||||
conf_names.push_back(joint_name + "/" + feedback_type()); | ||||||
} | ||||||
return {interface_configuration_type::INDIVIDUAL, conf_names}; | ||||||
} | ||||||
|
@@ -183,28 +189,36 @@ controller_interface::return_type DiffDriveController::update( | |||||
} | ||||||
else | ||||||
{ | ||||||
double left_position_mean = 0.0; | ||||||
double right_position_mean = 0.0; | ||||||
double left_feedback_mean = 0.0; | ||||||
double right_feedback_mean = 0.0; | ||||||
for (size_t index = 0; index < wheels.wheels_per_side; ++index) | ||||||
{ | ||||||
const double left_position = registered_left_wheel_handles_[index].position.get().get_value(); | ||||||
const double right_position = | ||||||
registered_right_wheel_handles_[index].position.get().get_value(); | ||||||
const double left_feedback = registered_left_wheel_handles_[index].feedback.get().get_value(); | ||||||
const double right_feedback = | ||||||
registered_right_wheel_handles_[index].feedback.get().get_value(); | ||||||
|
||||||
if (std::isnan(left_position) || std::isnan(right_position)) | ||||||
if (std::isnan(left_feedback) || std::isnan(right_feedback)) | ||||||
{ | ||||||
RCLCPP_ERROR( | ||||||
logger, "Either the left or right wheel position is invalid for index [%zu]", index); | ||||||
logger, "Either the left or right wheel %s is invalid for index [%zu]", feedback_type(), | ||||||
index); | ||||||
return controller_interface::return_type::ERROR; | ||||||
} | ||||||
|
||||||
left_position_mean += left_position; | ||||||
right_position_mean += right_position; | ||||||
left_feedback_mean += left_feedback; | ||||||
right_feedback_mean += right_feedback; | ||||||
} | ||||||
left_position_mean /= wheels.wheels_per_side; | ||||||
right_position_mean /= wheels.wheels_per_side; | ||||||
left_feedback_mean /= wheels.wheels_per_side; | ||||||
right_feedback_mean /= wheels.wheels_per_side; | ||||||
|
||||||
odometry_.update(left_position_mean, right_position_mean, current_time); | ||||||
if (odom_params_.position_feedback) | ||||||
{ | ||||||
odometry_.update(left_feedback_mean, right_feedback_mean, current_time); | ||||||
} | ||||||
else | ||||||
{ | ||||||
odometry_.updateFromVelocity(left_feedback_mean, right_feedback_mean, current_time); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not use
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You mean calculating There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we should have There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldnt this be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, I'm from mobile now, but your line of thought seems reasonable at a first look. In these days I'm on vacation so I can't evaluate and fix, maybe it is worth pushing a new PR with the fixes you have in mind explaining there what's wrong with current code. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It also doesn't really make sense to me why both pose and twist get computed from vel when this param is enabled. Doesn't it make more sense to compute odom pose using position deltas calculated from the position interface and then use instantaneous vel from the velocity interface to calculate the odom twist? This is the approach that the clearpath fork ended up using, allowing for two params to disable this behavior (originally implemented in clearpathrobotics/ros_controllers#18, but available in their latest indigo branch). Thoughts on this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @wmmc88 do you opened any issue or PR related to this? For your last message, I undestand that you are talking about using simultaneously the feedback position and velocity interfaces. Is is correct? In my undestanding, for now there is only support here for one of the two IF/s at time, but using both if available could be interesting (not to be seen as a bug, but as a feature enhancement). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
nope. havent opened an issue and haven't had any time to address it myself in a pr.
yeah this wasn't meant to be an issue with this pr. I'm more just suggesting as an enhancement that the pose be calculated by the position interface data and the twist be calculated from the velocity interface data. I believe that is a more optimal solution and that is what the linked clearpath fork did(they reverted a change similar to this pr and went with the pose from position/twist from velocity approach). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I reviewed now, and you are true. Since the code calls "vel" the position delta (misleadingly), I made confusion. A multiplication with |
||||||
} | ||||||
} | ||||||
|
||||||
tf2::Quaternion orientation; | ||||||
|
@@ -331,6 +345,7 @@ CallbackReturn DiffDriveController::on_configure(const rclcpp_lifecycle::State & | |||||
twist_diagonal.begin(), twist_diagonal.end(), odom_params_.twist_covariance_diagonal.begin()); | ||||||
|
||||||
odom_params_.open_loop = node_->get_parameter("open_loop").as_bool(); | ||||||
odom_params_.position_feedback = node_->get_parameter("position_feedback").as_bool(); | ||||||
odom_params_.enable_odom_tf = node_->get_parameter("enable_odom_tf").as_bool(); | ||||||
|
||||||
cmd_vel_timeout_ = std::chrono::milliseconds{ | ||||||
|
@@ -586,10 +601,12 @@ CallbackReturn DiffDriveController::configure_side( | |||||
registered_handles.reserve(wheel_names.size()); | ||||||
for (const auto & wheel_name : wheel_names) | ||||||
{ | ||||||
const auto interface_name = feedback_type(); | ||||||
const auto state_handle = std::find_if( | ||||||
state_interfaces_.cbegin(), state_interfaces_.cend(), [&wheel_name](const auto & interface) { | ||||||
state_interfaces_.cbegin(), state_interfaces_.cend(), | ||||||
[&wheel_name, &interface_name](const auto & interface) { | ||||||
return interface.get_name() == wheel_name && | ||||||
interface.get_interface_name() == HW_IF_POSITION; | ||||||
interface.get_interface_name() == interface_name; | ||||||
}); | ||||||
|
||||||
if (state_handle == state_interfaces_.cend()) | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
diff_drive_controller: | ||
test_diff_drive_controller: | ||
ros__parameters: | ||
left_wheel_names: ["left_wheels"] | ||
right_wheel_names: ["right_wheels"] | ||
|
@@ -17,6 +17,7 @@ diff_drive_controller: | |
pose_covariance_diagonal: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0] | ||
twist_covariance_diagonal: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0] | ||
|
||
position_feedback: false | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is there other option missing: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, in my previous comments I also observed that this file is not being loaded correctly by the tests. So I just added the line as an example of configuration and reference, but it is not being used by tests. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Long story short, we need to address this ticket: #48 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was not meaning to block this PR with that comment, just cross referencing |
||
open_loop: true | ||
enable_odom_tf: true | ||
|
||
|
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.
We should probably also rename this in the follow-up PR to make the variable name clearer.
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.
You mean choosing a different name than "feedback"? Suggestions?
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 think it's ok for now
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 am actually proposing to rename the "velocity" to "command" or something like this.