-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
[RPP] Project carrot beyond end of path if interpolating #3788
Conversation
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## main #3788 +/- ##
==========================================
+ Coverage 90.10% 90.20% +0.09%
==========================================
Files 431 417 -14
Lines 19393 18614 -779
==========================================
- Hits 17475 16790 -685
+ Misses 1918 1824 -94 ☔ View full report in Codecov by Sentry. |
@@ -322,23 +322,42 @@ geometry_msgs::msg::PoseStamped RegulatedPurePursuitController::getLookAheadPoin | |||
// If the no pose is not far enough, take the last pose | |||
if (goal_pose_it == transformed_plan.poses.end()) { | |||
goal_pose_it = std::prev(transformed_plan.poses.end()); | |||
} else if (params_->use_interpolation && goal_pose_it != transformed_plan.poses.begin()) { | |||
} | |||
if (params_->use_interpolation && goal_pose_it != transformed_plan.poses.begin()) { |
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.
Interpolation is regarding interpolating between path points for sparse paths / large vehicles for selecting the lookahead points at steady state.
I think this approach to goal stuff is something separate. Mostly because people might want this feature you're adding, but not care about path tracking interpolation
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.
Followup: I'd like to understand the behavior that this interpolation after the goal creates. If there's no reason that this isn't just always enabled, let me know and we can just make this the new default behavior without a parameterized option
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.
My reasoning is that if someone isn't turning on the interpolation then they (presumably) care about only having carrots that are poses from the path. Projecting off the end of the path would violate that as we are creating a new pose to track.
WRT the default behaviour - yes, I believe it should always be enabled. At the moment if you are asking for interpolated carrots, you are in effect asking for the planner to always produce a carrot that is exactly the lookahead distance from the robot. At the moment when approaching the goal this is not the case - the carrot gets closer and closer.
For an Ackermann steered vehicle where the base_link
is on the rear axle as you approach the goal the carrot ends up behind the front steering wheels. This makes it very unstable, and small cross-track errors lead to big deviations in yaw. With very little path left this very often ends up with the robot reaching the goal with very poor alignment (on our platform anyway!).
I have seen the other work done here on slowing down on approach to goal, and that is something that we are interested in because we also have a large platform with limits on how quickly it can speed up and slow down. But this PR isn't meant to address any of those things - just tracking of the path as the robot approaches the goal. All the calcs about when to start slowing down are done with reference to the last pose in the path, so this PR does not change that.
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 interpolation is mostly for smooth motion purposes so that between iterations that the velocity curves are more continuous -- which is important for larger vehicles that might have pretty sparse paths (this was created by an ag-tech company). I don't think the rationale is really about being on the exact path with exact path points.
WRT the default behaviour - yes, I believe it should always be enabled ... I have seen the other work done here on slowing down on approach to goal, But this PR isn't meant to address any of those things
Ah, do you think we could? For instance
- Do this forward projection to the lookahead distance
- But reduce the velocity in proportion to the distance remaining to the actual goal pose
If we had something like that, we could simply make it default then without a parameterization. In fact, isn't that the behavior with this enabled + approachVelocityConstraint
(which is non-optional)? I believe the slowdown logic is already decoupled the lookahead distance
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 interpolation is mostly for smooth motion purposes so that between iterations that the velocity curves are more continuous -- which is important for larger vehicles that might have pretty sparse paths (this was created by an ag-tech company). I don't think the rationale is really about being on the exact path with exact path points.
I was just guessing - I would never want to run without the interpolation on for exactly the reasons you state! ;) Even if the path wasn't sparse.
If we had something like that, we could simply make it default then without a parameterization. In fact, isn't that the behavior with this enabled + approachVelocityConstraint (which is non-optional)? I believe the slowdown logic is already decoupled the lookahead distance
Yes, the slowdown is already decoupled - it uses the current pose and last pose in the path as parameters. The carrot is not involved in those calculations.
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.
Honestly, this might be a kick for me to disable the option for interpolation and just have it happen. That was a new feature so I didn't want to break users, but its had enough baking time now I think it can just be always included. But something to do after this PR is figured out!
@doisyg please review :-) |
// Projecting past the last point by the lookahead distance ensures that the point | ||
// is at least the lookahead distance away | ||
// (maybe more, but we will interpolate in the next step) | ||
goal_position.x += dx / d * lookahead_dist; |
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... don't think this is correct
If the total distance between points is 1 unit and equal component X and Y, then dx
and dy
would be 0.7071
for a total d
of 1.0
. In that case, we're adding more to the goal pose than would be the length of the lookahead_distance
.
I think you need to do some trig with the angles to see what component of each you need to apply like the commit I originally linked to did, unless I'm missing something.
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.
Yes, that is deliberate because the direction is the important bit. The distance is truncated in the following code by the call:
https://github.com/ros-planning/navigation2/blob/681d7e15acbb27618272e0530d7b8f385d614fad/nav2_regulated_pure_pursuit_controller/src/regulated_pure_pursuit_controller.cpp#L353
I think you need to do some trig with the angles to see what component of each you need to apply like the commit I originally linked to did, unless I'm missing something.
This is the same as in the linked commit https://github.com/ros-planning/navigation2/blob/a9d8c4c9889c7d8684296c5d7733f507255520c1/nav2_regulated_pure_pursuit_controller/src/regulated_pure_pursuit_controller.cpp#L232-L239 just without using trig functions to convert to an intermediate angle.
The distance is set to the lookahead distance so that it is outside the radius and circleSegmentationIntersection()
succeeds.
The difference is approach is that in the previous work in a9d8c4c the remaining lookahead distance is calculated by taking the "path end as carrot" distance, and working out how much shorter than the lookahead distance it is. This distance is then added to the last segment of the path and treated as the new carrot. (There is an implicit assumption that the direction from the robot to the last path pose is the same as the direction of the last segment, but I suspect that in practice this would make very little difference/be very unlikely to cause problems as it would need odd dog-leg paths at the scale of the lookahead distance for it to matter).
My approach checks to see if the last pose is being selected before the call to find the circle-segment intersection (which runs for all interpolations along the path), and shifts the goal pose before this call. So every iteration uses the circle-segment intersection approach, even when it is on the last segment.
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.
👍 @doisyg thoughts? I suppose this is worth testing on your platform to let me know if this alternative works for you
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.
Trying to find a slot to test on a real big robot. Give me 24h
(There is an implicit assumption that the direction from the robot to the last path pose is the same as the direction of the last segment, but I suspect that in practice this would make very little difference/be very unlikely to cause problems as it would need odd dog-leg paths at the scale of the lookahead distance for it to matter).
Indeed, I developed and tested a9d8c4c for straight paths only. I agree this should be mostly fine for general paths but I did not make the exercise of thinking and testing about corner cases.
Hi @SteveMacenski and @doisyg The method proposed by @doisyg avoids this problem but it does so by just keeping the robot moving in a straight line at the end - ie it stops trying to align itself with the path direction at the end. We could adopt a hybrid approach - project the last segment until there is no segment to project and at that point project the robot->goal direction. There is also work that needs to be done to project the carrot at cusps in reversing paths - this will be trickier to solve cleanly. |
Is that necessarily problematic? If you're within a short distance of the path, you're probably a straight-line estimate from the goal anyway. The only time I would think that would be a problem is if you have a very, very high curvature path towards the end of the task. But in that case, we rotate to goal heading at the end so that could just trigger https://github.com/ros-planning/navigation2/blob/main/nav2_regulated_pure_pursuit_controller/src/regulated_pure_pursuit_controller.cpp#L214. I suppose it could be problamatic if its really confined and thus near obstacles, but I wouldn't think the tiny semantic change like that in path following would be the deciding factor. Is that a real problem you're aware of?
I suppose that's also an option. Seems like it might be overkill, but that would be fine with me as long as all of this was definitely broken out into another function. Then that should be good to go. If the path is only 1 point, then a straight line is all we can do anyway so that makes the above remarks moot.
All the planners generate an orientation at the end of the path. That's how the controller knows to rotate / achieve the right yaw portion of the pose. But only the feasible Smac Planners generate orientations at all subsequent poses in the path (except if any of the path smoothers are used with any planner; then they populate orientations as part of their work). Just a reminder to split this from the |
Agreed, one could want to interpolate on the path without interpolating the lookahead point after the goal. And if interpolating on the path becomes the default and the parameter disappears, we still want to be able to control if we want to interpolate the lookahead point or not. |
@james-ward any update? |
I re did it from scratch starting from main branch in botsandus@4d570f8 |
Sorry, did not get any notifications of new comments on this thread. Odd... The approach by @doisyg above is basically what I have done on a different branch - I chose to start again. https://github.com/james-ward/navigation2/tree/preserve-last-segment In all of these approaches there is still an issue with projecting past cusps in paths with reversals. I cannot see a nice way to do that at the present time. |
For reference we have been using that branch on our platform for the last three weeks and it has been a great improvement. |
@james-ward do you think we should use your new branch or @doisyg's for merging a fix into Nav2? Just trying to make sure we can rectify these two similar directions to get something that satisfies everyone! |
I'm happy with @doisyg's approach. I didn't do it that way because I was unsure if there might be problems if the controller has poses behind the robot after it has finished pruning. I was also going to update the documentation and add a warning if the minimum lookahead distance is non-zero and the new projection flag isn't turned on. If you are happy for me to make the history in this PR invalid I can force push my new branch to replace the one referenced in this PR which will make looking at my patch set easier. |
Yes please! @doisyg do you agree we should use his as well? |
681d7e1
to
24fd460
Compare
I'll let @doisyg give the first review analysis when he has some time |
This pull request is in conflict. Could you fix it @james-ward? |
24fd460
to
5dcb7b4
Compare
This pull request is in conflict. Could you fix it @james-ward? |
5dcb7b4
to
9de1624
Compare
Hi @doisyg @SteveMacenski |
I think its on @doisyg list for this week or next? |
Signed-off-by: James Ward <[email protected]>
Signed-off-by: James Ward <[email protected]>
Signed-off-by: James Ward <[email protected]>
Signed-off-by: James Ward <[email protected]>
bc8a89e
to
e9dd766
Compare
nav2_regulated_pure_pursuit_controller/src/regulated_pure_pursuit_controller.cpp
Outdated
Show resolved
Hide resolved
Signed-off-by: James Ward <[email protected]>
Signed-off-by: James Ward <[email protected]>
@RhysMcK Thanks for looking at this. I had to rebase a couple of times due to upstream changes, and some formatting changes came through. I have added a commit to remove them, so the only changes in this PR are now the algorithmic ones. Much easier to review! |
#4140 supersedes. Thanks @james-ward for your help and prototype here! |
Basic Info
Description of contribution in a few bullet points
Description of documentation updates required from your changes
None
Future work that may be required in bullet points
None
For Maintainers: