-
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
Feat/smac planner include orientation flexibility #4127
base: main
Are you sure you want to change the base?
Feat/smac planner include orientation flexibility #4127
Conversation
@stevedanomodolor what's the status here - do you want me to review in detail, have gaps that are TODO, or have some questions to discuss? I don't want to go through and nitpick some small issues if you're really looking for feedback elsewhere right 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 didn't review the analytic expansions yet, pending your answer to my above question. But overall from what I read so far, very few notes. This is very good and I couldn't have done it better myself!
If you consider the general approach to be ok, then you can review it in detail. If the approach is good, what is just left is to modify the test to take into consideration these changes hench the todo in the CMakelists. |
I think the analytic expansions might need to be rethought a bit. I think we should be taking all
I think your logic is that if we sort by heuristic, then the first that comes back as a valid expansion will be the shortest. I think that would generally be true if the heuristic was a very purist implementation of a distance heuristic. But instead, we have the maximum of a few heuristics including cost information so the "closest" and the one with the "lowest travel cost" aren't necessarily the same thing. So I think largely these changes should be taken back to square one unfortunately and loop to find each of the So after
You can use that best_score, store it for that particular angle to decide which to use. |
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 ran out of time this evening to review, but this is a few things -- also you have a number of linting issues I can see. Check CI for the full list of formatting problems
Its also ready enough to update docs for the new variable for the mode to describe the mode, and the migration guide update to show this feature. An image/gif of this in action with the different modes would be great! I looked through it and all looks good except the analytic expansions I didn't get to right 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.
Looks good!
I think you are missing some work for the distance heuristic.
The distance heuristic is pre computed based on free space. We current only calculate it for the the first goal. This means that we could artificially inflate the cost to go making the heuristic inadmissible.
My suggestion would be to remove the distance heuristic when we are in ALL_DIRECTION
mode. For the BIDIRECTIONAL
mode I would pre compute the distance for both angles and take the min of those two.
From what I have seen the distance heuristic is rarely greater than the obstacle heuristic so you probably haven't seen any issues.
Any questions or anything I can unblock on? 😄 |
@stevedanomodolor, your PR has failed to build. Please check CI outputs and resolve issues. |
2 similar comments
@stevedanomodolor, your PR has failed to build. Please check CI outputs and resolve issues. |
@stevedanomodolor, your PR has failed to build. Please check CI outputs and resolve issues. |
No blocking points, just making changes based on @jwallace42 feedback and testing them but after merging to the main and pulling the latest dockers, pr is not building. |
@stevedanomodolor, your PR has failed to build. Please check CI outputs and resolve issues. |
1 similar comment
@stevedanomodolor, your PR has failed to build. Please check CI outputs and resolve issues. |
Yeah there's a transient issue due to Rolling moving to 24.04 so a bunch of tooling and package indices are being messed with. Don't worry about it, its not your fault as long as it works locally. Just make sure to keep up on unit testing. Want me to take a look again? |
I will take advantage of the time to add more unit testing after making the modification you suggested. After the added unit tests, you can look into it. |
@stevedanomodolor, your PR has failed to build. Please check CI outputs and resolve issues. |
9 similar comments
@stevedanomodolor, your PR has failed to build. Please check CI outputs and resolve issues. |
@stevedanomodolor, your PR has failed to build. Please check CI outputs and resolve issues. |
@stevedanomodolor, your PR has failed to build. Please check CI outputs and resolve issues. |
@stevedanomodolor, your PR has failed to build. Please check CI outputs and resolve issues. |
@stevedanomodolor, your PR has failed to build. Please check CI outputs and resolve issues. |
@stevedanomodolor, your PR has failed to build. Please check CI outputs and resolve issues. |
@stevedanomodolor, your PR has failed to build. Please check CI outputs and resolve issues. |
@stevedanomodolor, your PR has failed to build. Please check CI outputs and resolve issues. |
@stevedanomodolor, your PR has failed to build. Please check CI outputs and resolve issues. |
Yeah that sounds good to me. I generally agree that this is probably the issue, I just want to know for sure before we assume too much :-) I'm trying to think of some strategies to speed this up (if this is the case): Check every- That way, normal searches that have no expanions possible completes |
The Hybrid-A* can have 64, 72, or other total bins it needs to check. The state lattice planner typically has ~16 since the primitives have to create a regularized lattice structure. You could do more, but typically 16 is sufficient. If you reduced Hybrid-A* to 16, do you see a similar result as the state lattice planner? |
To summarize our call: We should do a course-to-fine search rather than going for all N (72) bins. We could introduce a new parameter for the analytic expansion that is the coarse search resolution (default: 4). If we find any valid path in that coarse search, then we do the full resolution. If we make it default to 4, it should have similar characteristics to the state lattice performance. This should be relatively easy to implement using a queue and a while loop to replace the for loop, where it is initialized with every :-) |
yes, get the same result |
Oh great - that means what we discussed will almost definitely improve performance to that level! |
I tried the improvement, and it did reduce the overall time. 🎉 Now, I am testing another idea to further reduce the time for the distance heuristic. What do you think: The main issue with the current method of storing a loopup table that contains the minimum values for all directions is that the chosen minimum goal might still end up in collision. In addition during the isInputValid check, we discard goals that are in collision. As a result, the "minimum" value stored may not be valid. I propose the following, the first lookup table stores the distance as is now. In addition to this, i create another lookup table that for each position (x, y, θ) to (x,y,theta) i store the index of the position of the loop up table but sorted from minimum to maximum distance. During the isInputValid step, I create a boolean list that marks which goals are invalid (i.e., in collision) and gives this information to the distance heuristic. Using the Second Table, when evaluating the getDistance heuristic, we iterate through the indices in the second lookup table for the given (x, y, θ). We pick the first index corresponding to a goal that is not marked as invalid in the boolean list. I tried before to create another lookup table during the is input valid, but its takes a long time to do that loop. |
Yay! What's it look now?
I think I understand: You want to keep the current lookup table so that you can access any point, orientation to query (HLUT1). Then, create a second lookup table that contains for each X,Y cell a vector of indexes of HLUT1, sorted by distance (HLUT2). So the size would be the same as HLUT, but store a vector rather than a This is where you lose me.
Even if you had this, HLUT2 is sorted by distance. How do you know which distance belongs to which orientation? They're no longer ordered by orientation. You would probably need to store a Or, don't sort it at all and go through the vector and find the min that meets the condition that has its corresponding bool list value is true. Then the bool list is needed and would require a full iteration of the vector. I'd consider the memory impact of such a lookup table. If we have a HLUT dimension of 200x200 (10m at 5cm resolution) of floats, that's 0.32Mb. If we have each orientation stored as HLUT2 would have, say 72 as default, thats now 23Mb. For a HLUT of 20m x 20m (our default), that's 1.28Mb and 92Mb respectively. Double all these numbers if you store a Assuming that's an OK amount of memory to store, accessing a memory block of that size, then iterating through the vector may actually turn out to be slower than just iterating through HLUT1 72 times. Or not, we can't know without trying! Its a good idea and alot of these kind of things in Smac were done by 'just trying it out' and seeing what the results were Separately, depending on the metrics from the change you made that worked, we may not need to pull out additional performance improvements by pushing more into lookup tables. But, we certainly could. I think if we did something like that, it should be in a follow up PR as to not muddle up the great work done here and decouple the complexity a bit. The |
Signed-off-by: stevedan <[email protected]>
Signed-off-by: stevedan <[email protected]>
will sync with latest and test again and show the results. |
Signed-off-by: stevedan <[email protected]>
@SteveMacenski Finally got some good results. Before optimization
After Optimization
Will cleanup and push for review |
Signed-off-by: stevedan <[email protected]>
Signed-off-by: stevedan <[email protected]>
Signed-off-by: stevedan <[email protected]>
970dc17
to
4310427
Compare
Signed-off-by: stevedan <[email protected]>
Signed-off-by: stevedan <[email protected]>
Signed-off-by: stevedan <[email protected]>
Signed-off-by: stevedan <[email protected]>
Signed-off-by: stevedan <[email protected]>
Signed-off-by: stevedan <[email protected]>
Signed-off-by: stevedan <[email protected]>
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.
Overall looks really good to me, I have a couple of small changes and after that the next review I'll go into detail line by line to make sure we didn't miss anything subtle, but its largely code I've already reviewed pre-coarse search and approved, so its more just for my piece of mind (and don't expect to find any issues).
Please pull in the updates from the main branch (some smac optimizations were made) and benchmark against your changes with main pulled in and the new main itself. If they are similar/same/better, then this is good to go!
_goal_heading_mode = fromStringToGH(goal_heading_type); | ||
|
||
nav2_util::declare_parameter_if_not_declared( | ||
node, name + ".coarse_search_resolution", rclcpp::ParameterValue(4)); |
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.
for both planners: check that this is an exact increment of the lattice or hybrid primitive set (i.e. equally divisible so that we don't end up with like prim_set.size() / coarse_resolution = 2.3535. It should be 2 or 3). Otherwise, in the code, we need to explicitly set a policy for handling this. overall though, I think its a misconfiguration if someone selects something non-exact, so throwing and failing to configure / do a param update seems OK
Also for the lattice planner: I think this should default to the lattice's size and not do coarse resolution (so default = 1 whereas hybrid = 4). The doc PR should be updated accordingly
_logger, "coarse iteration resolution selected as <= 0, " | ||
"disabling coarse iteration resolution search for goal heading" | ||
); | ||
_coarse_search_resolution = 0; |
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.
Here and in the other file (and in the dynamic parameters): Shouldn't this be 1? I don't think 0
is a valid configuration. I know you error check for 0
to replace with 1
, but I think we should still set 1
(and have the 0
check throw an exception?)
Basic Info
Description of contribution in a few bullet points
Description of documentation updates required from your changes
How to run
Future work that may be required in bullet points
For Maintainers: