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 mppi bidirectional settings #4954

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

mini-1235
Copy link
Contributor

@mini-1235 mini-1235 commented Mar 1, 2025


Basic Info

Info Please fill out this column
Ticket(s) this addresses #4601
Primary OS tested on Ubuntu
Robotic platform tested on gazebo sim
Does this PR contain AI generated software? NO

Description of contribution in a few bullet points

Description of documentation updates required from your changes

None

Description of how this change was tested

Tested on sim, wrote some new unit tests


Future work that may be required in bullet points

Maybe more unit tests? Looking for some suggestions before proceeding

For Maintainers:

  • Check that any new parameters added are updated in docs.nav2.org
  • Check that any significant change is added to the migration guide
  • Check that any new features OR changes to existing behaviors are reflected in the tuning guide
  • Check that any new functions have Doxygen added
  • Check that any new features have test coverage
  • Check that any new plugins is added to the plugins page
  • If BT Node, Additionally: add to BT's XML index of nodes for groot, BT package's readme table, and BT library lists

Copy link

codecov bot commented Mar 1, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Files with missing lines Coverage Δ
...ler/include/nav2_mppi_controller/motion_models.hpp 100.00% <100.00%> (ø)
nav2_mppi_controller/src/optimizer.cpp 99.19% <100.00%> (+<0.01%) ⬆️

... and 3 files with indirect coverage changes

float max_delta_vx = model_dt_ * control_constraints_.ax_max;
float min_delta_vx = model_dt_ * control_constraints_.ax_min;

float max_delta_vx = 0.0;
Copy link
Member

Choose a reason for hiding this comment

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

Why were these changed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Assigning here is meaningless, we have moved it into the for loop, I can do it like this or float max_delta_vx; if you prefer

Copy link
Member

Choose a reason for hiding this comment

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

Agreed its meaningless, but vy and wz didn't have this change, so we should make it consistent. Remove all or revert the vx ones please

} else {
max_delta_vx = -control_constraints_.ax_min * model_dt_;
min_delta_vx = control_constraints_.ax_min * model_dt_;
}
Copy link
Member

Choose a reason for hiding this comment

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

I think this is also missing for Y direction as well

Copy link
Contributor Author

@mini-1235 mini-1235 Mar 7, 2025

Choose a reason for hiding this comment

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

I didn't see the ay_min as well as az_min at first, so I only deal with the X direction, are we assuming that ay_min = - ay_max?

Copy link
Member

Choose a reason for hiding this comment

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

It looks like ay_min is accidentally missing and should be added. If ax_max is max acceleration and ax_min is max deceleration, then the Y axis should have the same as another translational motion axis.

The max acceleration should be applied for moving full-left and full-right (with appropriate sign changes to accomodate); while the deceleration is applied to slowing down movements both left and right.

Accelerating forward is ax_max, decelerating forward is ax_min. Accelerating in reverse is -ax_max and decelerating in reverse is -ax_min.

Copy link
Contributor

Choose a reason for hiding this comment

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

So, I think that really this should only be looking at the sign of vx_last to know what to populate for min_delta_vx and max_delta_vx. I don't see why a comparison with cvx_curr or cvx_curr * vx_last >= 0.0 is necessary here. Does that make sense?

Yes, the sign of vx_last should be enough to determine the delta values.

Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like ay_min is accidentally missing and should be added.

When I was working on adding constraints, there was some discussion around it, as I remember.
#4352 (comment)
#4352 (comment)

// Decelerating otherwise
if (abs(cvx_curr) >= abs(vx_last) && cvx_curr * vx_last >= 0.0) {
max_delta_vx = control_constraints_.ax_max * model_dt_;
min_delta_vx = -control_constraints_.ax_max * model_dt_;
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't this be ax_min not max? We are setting the bounds of max acceleration, and max deceleration when we're currently accelerating.

I think this should just be

min_delta_vx = control_constraints_.ax_min * model_dt_;

(the usual)

Ditto issue in the else condition. I think that should be the one inverting the signs and/or the value positions

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am actually following the convention here

if (abs(v_cmd) >= abs(v_curr) && v_curr * v_cmd >= 0.0) {
v_component_max = accel / smoothing_frequency_;
v_component_min = -accel / smoothing_frequency_;
} else {
v_component_max = -decel / smoothing_frequency_;
v_component_min = decel / smoothing_frequency_;

shouldn't we stay consistent for that?

Copy link
Member

Choose a reason for hiding this comment

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

Let me look over this again, admittedly I'm a bit sick and may have just misinterpreted this

Copy link
Member

@SteveMacenski SteveMacenski Mar 11, 2025

Choose a reason for hiding this comment

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

Writing this out as part of the process. Accelerations min/max are signed (i.e. a_max is positive, a_min is negative).

I see the following cases, centered around how we find the viable bounds to place on cvx_curr for what is dynamically feasible. We start with our current velocity from the last iteration, vx_last and we want to find the values above and below it to threshold current control step cvx_curr for:

  1. Moving forward, meaning vx_last which is positive
  • +ax_max * model_dt for maximum forward velocity possible while accelerating (numerically highest value)
  • +ax_min * model_dt for minimum forward velocity possible while decelerating (numerically lowest value)
  • Thus we clamp in the low-high range of (vx_last + ax_min * model_dt, vx_last + ax_max * model_dt)
  1. Moving in reverse, meaning vx_last which is negative
  • -ax_max * model_dt for maximum reverse velocity possible while accelerating (numerically lowest value)
  • -ax_min * model_dt for minimum reverse velocity possible while decelerating (numerically highest value)
  • Thus we clamp in the low-high range of (vx_last - ax_max * model_dt, vx_last - ax_min * model_dt)

If the robot is moving forward but the next velocity is in reverse due to random sampling, that should cover the scope as the bounds are already placed.

So, I think that really this should only be looking at the sign of vx_last to know what to populate for min_delta_vx and max_delta_vx. I don't see why a comparison with cvx_curr or cvx_curr * vx_last >= 0.0 is necessary here. Does that make sense?

I believe what is done in the velocity smoother is different. It is putting the bounds on the acceleration part of the term to allow in the velocity smoother between iterations when we have already identified if we're accelerating or decelerating. Note the dv is v_cmd - v_curr and we're clamping on the accelerating part of the term, not the full velocity (which v_curr is added - right @doisyg?

@@ -86,6 +87,15 @@ class MotionModel
for (unsigned int j = 0; j != n_rows; j++) {
float vx_last = state.vx(j, i - 1);
float & cvx_curr = state.cvx(j, i - 1);
// Accelerating if magnitude of cvx is greater than vx_last and they have the same sign
// Decelerating otherwise
Copy link
Member

Choose a reason for hiding this comment

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

I don't believe this is true. There are four potential states:

  • Accelerating forward
  • Decelerating forward
  • Accelerating in reverse
  • Decelerating in reverse

I don't think this properly handles all 4 cases.

@Ayush1285 do you mind taking a look / reviewing this as well? Your recent changes touch this part of code as well

Copy link
Contributor

Choose a reason for hiding this comment

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

Sure, I'll review it.

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.

3 participants