Skip to content

Call ExecuteTrajectoryAction while planning#3676

Merged
rhaschke merged 14 commits intomoveit:masterfrom
rivelinrobotics:execute_while_planning
Jan 7, 2025
Merged

Call ExecuteTrajectoryAction while planning#3676
rhaschke merged 14 commits intomoveit:masterfrom
rivelinrobotics:execute_while_planning

Conversation

@riv-mjohnson
Copy link
Copy Markdown
Contributor

@riv-mjohnson riv-mjohnson commented Dec 12, 2024

Description

N.B. it was already possible to plan while a trajectory was executing with MoveGroupExecuteTrajectoryAction. This PR just allows new trajectories to start executing while planning.

Open questions:

  • Is this change to PlanningSceneMonitor the best way to avoid locking out the CurrentStateMonitor? Or do we want something a little more targeted to the specific callback the PlanningSceneMonitor adds to the CurrentStateMonitor?

Checklist

  • Required by CI: Code is auto formatted using clang-format
  • Extend the tutorials / documentation reference
  • Document API changes relevant to the user in the MIGRATION.md notes
  • Create tests, which fail without this PR reference
  • Include a screenshot if changing a GUI
  • While waiting for someone to review your request, please help review another open pull request to support the maintainers

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Dec 12, 2024

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

Attention: Patch coverage is 0% with 13 lines in your changes missing coverage. Please review.

Project coverage is 0.00%. Comparing base (5e249e9) to head (0e6ce8e).
Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
...nning_scene_monitor/src/planning_scene_monitor.cpp 0.00% 7 Missing ⚠️
...abilities/execute_trajectory_action_capability.cpp 0.00% 6 Missing ⚠️

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #3676       +/-   ##
==========================================
- Coverage   47.85%   0.00%   -47.84%     
==========================================
  Files         604     582       -22     
  Lines       61108   57364     -3744     
  Branches     7029    7142      +113     
==========================================
- Hits        29235       0    -29235     
- Misses      31455   57364    +25909     
+ Partials      418       0      -418     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Copy Markdown
Contributor

@rhaschke rhaschke left a comment

Choose a reason for hiding this comment

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

Adding a second spinner not only allows for parallel processing of execution and planning requests, but of any two ROS events. I'm afraid, the code is not prepared for this concurrency.

@riv-mjohnson
Copy link
Copy Markdown
Contributor Author

Sure, that's why I'm asking about mutexes. I'm thinking of something like a planning mutex and an executing mutex, so only planning+executing can happen concurrently, not e.g. planning+planning.

@riv-mjohnson
Copy link
Copy Markdown
Contributor Author

This would be easier in ros2, with a separate spinner for the trajectory execution manager, but should still be achievable in ros1.

@rhaschke
Copy link
Copy Markdown
Contributor

rhaschke commented Dec 12, 2024

I was thinking of a separate spinner and callback queue for trajectory execution as well. This is possible in ROS1.
You just need to use a custom callback queue (instead of the default one) for all relevant subscribers, services, actions, etc.
https://wiki.ros.org/roscpp/Overview/Callbacks%20and%20Spinning#Advanced:_Using_Different_Callback_Queues

@riv-mjohnson
Copy link
Copy Markdown
Contributor Author

Ooh, I did not know about this. I will take a look, thanks.

@riv-mjohnson
Copy link
Copy Markdown
Contributor Author

riv-mjohnson commented Dec 12, 2024

@rhaschke I've replaced the second spinner thread with a dedicated spinner in MoveGroupExecuteTrajectoryAction.

I'm slightly surprised this works; I was expecting to need to add some kind of spinner to the CurrentStateMonitor, but my test setup seems happy.

^ Nevermind, I see the planning scene monitor has its own spinner, so the CurrentStateMonitor is happy. I'm happy that this solution should work.

@riv-mjohnson riv-mjohnson changed the title Execute while planning Call ExecuteTrajectoryAction while planning Jan 6, 2025
@riv-mjohnson
Copy link
Copy Markdown
Contributor Author

@rhaschke @sea-bass

Happy new year.

Could this PR get re-reviewed? I'm keen to get it merged in to ROS1 and then port to ROS2.

Copy link
Copy Markdown
Contributor

@v4hn v4hn left a comment

Choose a reason for hiding this comment

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

I just looked into this for a while and the spinner for the separate queue should be fine.

The early return in updateSceneWithCurrentState seems problematic though and needs more details in my opinion.

Please rebase the branch to enable the required jammy and noble CI checks.

Copy link
Copy Markdown
Contributor

@v4hn v4hn left a comment

Choose a reason for hiding this comment

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

Personally I'm fine with the proposed patch, as it improves the current situation.
Thank you for contributing.
A clean rebase (instead of merging from master) would be appreciated.

Not sure whether you or @rhaschke want to address the bigger design issue (which needs some additional verification) of where to set state_update_pending_.

@riv-mjohnson
Copy link
Copy Markdown
Contributor Author

riv-mjohnson commented Jan 7, 2025

A clean rebase (instead of merging from master) would be appreciated.

I think I've now rebased. I'm not very familiar with rebasing, so I don't know if it worked properly.

The network graph looks right, but the commit history is a mess, with most commits duplicated. I don't know if this is expected?

@rhaschke
Copy link
Copy Markdown
Contributor

rhaschke commented Jan 7, 2025

I think I've now rebased. I'm not very familiar with rebasing, so I don't know if it worked properly.

You managed to rebase locally. be49dc4 is the correct HEAD.

The network graph looks right, but the commit history is a mess, with most commits duplicated. I don't know if this is expected?

... but messed up subsequently by merging your rebased branch back into your PR branch.
You need to force-push be49dc4 to your PR branch to fix this:

git push --force-with-lease https://github.com/rivelinrobotics/rivelin_moveit be49dc416a16e8da9000ddd9d5cc7d5306c12210:execute_while_planning

@riv-mjohnson riv-mjohnson force-pushed the execute_while_planning branch from dc1a8b9 to be49dc4 Compare January 7, 2025 11:12
@riv-mjohnson
Copy link
Copy Markdown
Contributor Author

Thanks for the pointers.

I tried with be49dc4, but the linting failed, so I retried with c8b1952. This seems to duplicate the "Fixes formatting" commit, but does fix the formatting.

Copy link
Copy Markdown
Contributor

@rhaschke rhaschke left a comment

Choose a reason for hiding this comment

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

Generally, I approve this as well. However, I have some cleanup suggestions filed as rivelinrobotics#17.

@riv-mjohnson
Copy link
Copy Markdown
Contributor Author

Does moveit use a style guide which covers the (bool skip_update_if_locked) vs (const bool skip_update_if_locked) case? You've both suggested it be changed in opposite directions.

@rhaschke
Copy link
Copy Markdown
Contributor

rhaschke commented Jan 7, 2025

Does moveit use a style guide which covers the (bool skip_update_if_locked) vs (const bool skip_update_if_locked) case?

As the argument is passed by value, const is not needed from the caller's perspective. Not using const allows the function to (re)use the variable in some other fashion. Declaring it const, forbids that too.
I think, MoveIt code tends to avoid const for passed-by-value args.

You've both suggested it be changed in opposite directions.

I'm not aware of that.

@riv-mjohnson
Copy link
Copy Markdown
Contributor Author

riv-mjohnson commented Jan 7, 2025

Generally, I approve this as well. However, I have some cleanup suggestions filed as rivelinrobotics#17.

Thanks for these. I've left one comment on your PR: I'm not sure if the 0.1 second timeout will play nicely with the other timeouts when calling getCurrentState?

(I've also left a minor linting comment - I assume your auto formatter has the same wrong settings as mine). - ignore this, it was caused by the reverting of too much, as below.

@riv-mjohnson
Copy link
Copy Markdown
Contributor Author

riv-mjohnson commented Jan 7, 2025

You've both suggested it be changed in opposite directions.

I'm not aware of that.

Oh, sorry, I think something is going wrong between your PR and the rebasing, which means your PR is undoing some of my PR? (Specifically the formatting error fixes and the const change)?

I think your commit to revert one of my commits reverted more than you intended? rivelinrobotics@94a71f3

@riv-mjohnson
Copy link
Copy Markdown
Contributor Author

I've rebase-merged your PR into mine. I'll just fix the extra things that were reverted, one sec.

@riv-mjohnson
Copy link
Copy Markdown
Contributor Author

Okay, I think everything is as it should be now.

@riv-mjohnson
Copy link
Copy Markdown
Contributor Author

And yes, I think I misremembered the other timeouts being 0.1s rather than 1s, so the 0.1s timeout is fine. I am happy with all the changes here now.

@riv-mjohnson riv-mjohnson force-pushed the execute_while_planning branch from d19ecf8 to 0e6ce8e Compare January 7, 2025 15:09
@rhaschke rhaschke merged commit 3aed1dc into moveit:master Jan 7, 2025
boost::unique_lock<boost::shared_mutex> ulock(scene_update_mutex_, boost::defer_lock);
if (!skip_update_if_locked)
ulock.lock();
else if (!ulock.try_lock_for(boost::chrono::duration<double>(std::min(0.1, 0.1 * dt_state_update_.toSec()))))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

at least formally dt_state_update_ is protected by state_pending_mutex_ which you don't hold here.
I don't think it's necessary to wait here at all.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Locking of the planning scene due to planning is only one locking scenario. Most of them hold the lock only shortly, e.g. by scenePublishingThread(), getPlanningSceneServiceCallback(), clearOctomap(), etc.
Thus, I thought that we should wait for the lock to become available and correctly finish the update.
Otherwise, we might get very irregular update frequencies most of the time.
However, I agree that we might want to use a fixed duration:

-       else if (!ulock.try_lock_for(boost::chrono::duration<double>(std::min(0.1, 0.1 * dt_state_update_.toSec()))))
+       else if (!ulock.try_lock_for(boost::chrono::milliseconds(100)))

The concrete duration is debatable. Probably, 10ms are fine too. I have no idea. Ideally, we should collect some real-world statistics...
Anyway: In the past we waited forever. Thus 100ms is a tremendous improvement.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

at least formally dt_state_update_ is protected by state_pending_mutex_ which you don't hold here.

I removed dt_state_update_ in 57563e2 of #3682.

rhaschke added a commit to ubi-agni/moveit that referenced this pull request Feb 6, 2025
…veit#3676)

This allows parallel execution + planning.

Also required modifying updateSceneWithCurrentState() to allow skipping a scene update with a new robot state (from CurrentStateMonitor), if the planning scene is currently locked (due to planning).
Otherwise, the CurrentStateMonitor would block too.

Co-authored-by: Robert Haschke <rhaschke@techfak.uni-bielefeld.de>
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.

The TrajectoryExecutionManager uselessly block on the PlanningSceneMonitor Allow simultaneous planning and execution

4 participants