Skip to content

Conversation

Amronos
Copy link
Contributor

@Amronos Amronos commented Aug 6, 2025

Fixes #271.
Fixes #357.

I have updated the odometry implementation of the diff_drive_controller to fix the above two issues alongside improving the code's readability. This implementation is similar to that of omni_wheel_drive_controller.
I have created some new methods and deprecated the older ones.

Should I also make similar changes to other controllers? If yes, should I do that in a separate PR?

Copy link

codecov bot commented Aug 6, 2025

Codecov Report

❌ Patch coverage is 81.08108% with 14 lines in your changes missing coverage. Please review.
✅ Project coverage is 85.03%. Comparing base (42e7ba4) to head (8ecb548).

Files with missing lines Patch % Lines
...iff_drive_controller/src/diff_drive_controller.cpp 83.33% 4 Missing and 3 partials ⚠️
diff_drive_controller/src/odometry.cpp 78.12% 6 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1854      +/-   ##
==========================================
- Coverage   85.25%   85.03%   -0.22%     
==========================================
  Files         143      143              
  Lines       13790    13819      +29     
  Branches     1197     1199       +2     
==========================================
- Hits        11756    11751       -5     
- Misses       1636     1671      +35     
+ Partials      398      397       -1     
Flag Coverage Δ
unittests 85.03% <81.08%> (-0.22%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...troller/include/diff_drive_controller/odometry.hpp 100.00% <ø> (ø)
...iff_drive_controller/src/diff_drive_controller.cpp 82.79% <83.33%> (+0.21%) ⬆️
diff_drive_controller/src/odometry.cpp 50.00% <78.12%> (-26.32%) ⬇️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Contributor

@christophfroehlich christophfroehlich left a comment

Choose a reason for hiding this comment

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

Let's discuss my points first, and merge the outcome. If necessary, let's open a new PR afterwards for the other controllers.

bool Odometry::updateFromVel(
const double & left_vel, const double & right_vel, const rclcpp::Time & time)
{
const double dt = time.seconds() - timestamp_.seconds();
Copy link
Contributor

Choose a reason for hiding this comment

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

this is exactly the pattern mentioned with #271 to be removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry, I should have explained this in the PR description.
The reasoning here is the same as that of this #260 (comment).
Additionally, timestamp_ records the last time an update was run; therefore, the correct value of dt can only be obtained from there.
It is used in this function despite (std::fabs(dt) < 1e-6) not being used, as it is also called from updateFromPos() which uses the timestamp_ variable.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry, I still don't understand. Why not using the period argument from the update method and pass it to the update method?

Copy link
Contributor Author

@Amronos Amronos Sep 9, 2025

Choose a reason for hiding this comment

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

  • Basically due to the if (std::fabs(dt) < 1e-6) {return false;} check in updateFromPos() we need to maintain the timestamp_ variable.
  • timestamp_ is only updated when the check returns false, and we continue with the code. If timestamp_ was updated every time, it would yield incorrect results, as we only update odometry when the code passes through that check.
  • If period was directly passed, then it would yield an incorrect dt (dt will now be replaced with period), as the current way to calculate dt is through the timestamp_, which is not updated every time the method is called.
  • The updateFromVel() function can be changed to use period if the arguments of updateFromPos() remain the same, and we pass it dt from there when using position feedback, and when using velocity feedback, we pass period from the main update method. This can only be done, though, if we are sure that the user can't/won't switch between velocity and position feedback while the controller is running (add read_only parameters to diff_drive_controller #1781).

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks, I understand the motivation now.

  1. Is the period argument ever that small so we need the check? (might come from ROS 1 days)
  2. If so (maybe the first update call after activation or something like this. This can't happen on a regular basis), Is the error really that high if we use the period and still skip if it is close to zero?

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

  1. I also thought about this, as the period argument would only be this small if the update rate is 10^6; I don't think people set the update rate that high, but I still kept the check. Because of Period is zero at first loop of ros controller ros2_control#2336, ig we will either way need it.
  2. Didn't think about it like that :). There would only be a minor 10^-6 or less seconds unaccounted for, which shouldn't have any effect on the odometry. That is assuming that the update rate would never be set that high to make this error accumulate.

So should I pass period to both the functions, in updateFromPos() keep the zero check, and stop the use of timestamp_ in the new functions?

Copy link
Contributor

Choose a reason for hiding this comment

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

yes please do so 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in 77eade3.

linear_ = linear_vel;
angular_ = angular_vel;

return true;
Copy link
Contributor

Choose a reason for hiding this comment

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

why a return value, which is always true?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is there to maintain consistency with other update methods, make it easier to add code to this function in the future that may return false, and make the diff_drive_controller.cpp code simpler.
updateFromVel() also has this line for the same reason.
I can change everything back to the normal updateOpenLoop() function if needed, though.

Amronos and others added 4 commits August 20, 2025 19:03
@Amronos
Copy link
Contributor Author

Amronos commented Sep 4, 2025

Sorry for the delay in fixing the failing checks here! I was busy shifting Linux distros and had tried to make the commits that caused the checks to fail through the web.

Copy link
Contributor

@christophfroehlich christophfroehlich left a comment

Choose a reason for hiding this comment

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

Still not sure about the tryUpdateOpenLoop method, maybe @saikishor or anyone else has an opinion about that.

bool Odometry::updateFromVel(
const double & left_vel, const double & right_vel, const rclcpp::Time & time)
{
const double dt = time.seconds() - timestamp_.seconds();
Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry, I still don't understand. Why not using the period argument from the update method and pass it to the update method?

Amronos and others added 2 commits September 9, 2025 15:08
Co-authored-by: Christoph Fröhlich <christophfroehlich@users.noreply.github.com>
@Amronos
Copy link
Contributor Author

Amronos commented Sep 24, 2025

@christophfroehlich pre-commit isn't working for me for some reason, but besides that I have made the changed you requested. If possible, could you clone the pr, and push a fix for the pre-commit? Thanks!

Copy link
Contributor

mergify bot commented Oct 3, 2025

This pull request is in conflict. Could you fix it @Amronos?

@Amronos
Copy link
Contributor Author

Amronos commented Oct 3, 2025

Sorry for the delay on this! All requested changes have been made now, please review!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants