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

Fix differential drive motion model #267

Merged
merged 5 commits into from
Nov 14, 2023
Merged

Conversation

hidmic
Copy link
Collaborator

@hidmic hidmic commented Nov 5, 2023

Proposed changes

Going over the math a few times, it doesn't seem to me that the rotation variance computation distributes over rotation composition. Not with those nonlinear max, min, abs operations in between.

Type of change

  • 🐛 Bugfix (change which fixes an issue)
  • 🚀 Feature (change which adds functionality)
  • 📚 Documentation (change which fixes or extends documentation)

Checklist

  • Lint and unit tests (if any) pass locally with my changes
  • I have added tests that prove my fix is effective or that my feature works
  • I have added necessary documentation (if appropriate)
  • All commits have been signed for DCO

Additional comments

Not sure how to write a test for this. Would a formal proof (that rotation_variance(a) * rotation_variance(b) != rotation_variance(a * b)) do?

Rotation variance computations does not distribute over rotation composition

Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
@glpuga
Copy link
Collaborator

glpuga commented Nov 5, 2023

Going over the math a few times, it doesn't seem to me that the rotation variance computation distributes over rotation composition. Not with those nonlinear max, min, abs operations in between.

I totally agree that that operation most definitely is not distributive.

However, I have broader concerns regarding the rotation_variance() function itself. From what I gather it's meant to bring the 2nd/3rd quadrant rotation values to the 1st/4th quadrant when moving backwards, needed because $\Delta x$ is negative (plus also squaring the result angle).

But that seems to be done at the end of all the math. By then, we already calculated the second rotation using the pre-adjustment first rotation, and it's not obvious to me that that can be fixed by moving second rotation back into 1st/4th quadrant too afterwards.

Not having gone through t all the math in Prob. Robotics, the definitions of $\delta_{rot1}$ and $\delta_{rot2}$ seem very straightforward (the aperture angles between the end/star pose and the direction between the end/start pose, range $-\pi/2$ to $\pi/2$). Maybe we should just do the quadrant adjustment once when calculating first $\delta_{rot1}$ the first time; that should take care of $\delta_{rot2}$ right away.

Additional comments

Not sure how to write a test for this. Would a formal proof (that rotation_variance(a) * rotation_variance(b) != rotation_variance(a * b)) do?

From this code we don't really have good observability to the results of this function, which would be the best way to test this. Given that the parameters are private you can only test by generating samples of the distribution and comparing it, which is not ideal.

I think it's worth either

  1. providing observability to the distribution parameter values through getters for testing's sake (not a fan),
  2. better yet, architecting this differently so that the actual code that does this critical calculation is in an external function/class that can be tested independently, feeding in pose and last_pose, and getting the distribution parameters at the other end, like we do with calculate_covariance() in the estimation mixin.

In this last scenario update_motion() would just call this function to calculate the distribution parameters, and manage the mixin last_pose_ state.

@hidmic
Copy link
Collaborator Author

hidmic commented Nov 6, 2023

From what I gather it's meant to bring the 2nd/3rd quadrant rotation values to the 1st/4th quadrant when moving backwards, needed because $\Delta x$ is negative (plus also squaring the result angle).

IIUC it's computing the minimum rotation angle magnitude. Because the model assumes forward motion, moving backwards means larger rotations than necessary (e.g. $(0, -1, 0)$ is expressed as $(\pi, 1, -\pi)$ ).

Maybe we should just do the quadrant adjustment once when calculating first $\delta_{rot1}$ the first time; that should take care of $\delta_{rot2}$ right away.

I guess we could. The mean of the translation distribution would have to be negative.

better yet, architecting this differently so that the actual code that does this critical calculation is in an external function/class that can be tested independently

Sounds reasonable.

@nahueespinosa
Copy link
Member

Given that the parameters are private you can only test by generating samples of the distribution and comparing it, which is not ideal.

FWIW, we have tests that generate samples and assert distribution parameter values, no need to provide observability to the internal state.

ASSERT_NEAR(stddev, std::sqrt(alpha * flipped_angle * flipped_angle), 0.01);

Factoring out the critical calculation is also very reasonable, but the other option is not that bad IMO.

BTW, thanks for digging in, this is great!

@glpuga
Copy link
Collaborator

glpuga commented Nov 6, 2023

FWIW, we have tests that generate samples and assert distribution parameter values, no need to provide observability to the internal state.

ASSERT_NEAR(stddev, std::sqrt(alpha * flipped_angle * flipped_angle), 0.01);

Good point. Bears asking why that test in insensitive to this fix then.

In that test, the translation distance is zero, so first_rotation would be zero and the result both after and before the change would be the same, right?.

@nahueespinosa
Copy link
Member

In that test, the translation distance is zero, so first_rotation would be zero and the result both after and before the change would be the same, right?.

Right, I would imagine a new test where all parameters but translation_noise_from_rotation are zero, and we set a move that requires two rotations. I volunteer to give it a shot tonight if it helps.

Signed-off-by: Nahuel Espinosa <nespinosa@ekumenlabs.com>
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
@hidmic hidmic merged commit bac478d into main Nov 14, 2023
7 checks passed
@hidmic hidmic deleted the hidmic/fix-diff-drive-model branch November 14, 2023 11:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants