Skip to content

Commit 9b6b6d7

Browse files
committed
WIP
Signed-off-by: methylDragon <[email protected]>
1 parent 2a2c8c2 commit 9b6b6d7

11 files changed

+261
-2
lines changed
Binary file not shown.
Binary file not shown.

doc/how_to_guides/how_to_guides.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Configuring and Using MoveIt
2525
pick_ik/pick_ik_tutorial
2626
trac_ik/trac_ik_tutorial
2727
benchmarking/benchmarking_tutorial
28+
trajectory_cache/trajectory_cache_tutorial
2829

2930
Developing and Documenting MoveIt
3031
---------------------------------
Loading
Loading
Loading
Loading
Loading
Loading

doc/how_to_guides/trajectory_cache/src/trajectory_cache_demo.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,20 @@
5656
*
5757
* NOTE:
5858
* Tutorial notes will be commented like this block!
59-
*
59+
*
6060
* PRE-REQUISITES
6161
* ^^^^^^^^^^^^^^
6262
* This tutorial assumes knowledge of the MoveGroupInterface.
6363
*
6464
* INTERACTIVITY
6565
* ^^^^^^^^^^^^^
66+
* This demo has four phases that can be advanced using the `rviz_visual_tools` dialog box.
67+
*
68+
* 1. Plan and cache (no pruning)
69+
* 2. Plan and cache (with pruning)
70+
* 3. Fetch from cache and execute (while still planning and caching with pruning)
71+
* 4. Fetch from cache and execute, except with large start tolerances
72+
*
6673
* This tutorial also supports "reconfigurable" parameters!:
6774
*
6875
* You can adjust them with:
@@ -71,7 +78,7 @@
7178
* Tutorial parameters:
7279
* - planner:
7380
* Defaults to "RRTstar". The OMPL planner used.
74-
* It's better to use a random-sampling, non-optimal planner to see the cache working.
81+
* It is better to use a random-sampling, non-optimal planner to see the cache working.
7582
*
7683
* Cache parameters:
7784
* - start_tolerance:
@@ -648,6 +655,19 @@ int main(int argc, char** argv)
648655

649656
// Interactivity. ================================================================================
650657

658+
/** [TUTORIAL NOTE]
659+
* This demo has four phases that can be advanced using the `rviz_visual_tools` dialog box.
660+
*
661+
* 1. Plan and cache (no pruning)
662+
* - Showcases basic cache functionality.
663+
* 2. Plan and cache (with pruning)
664+
* - Showcases pruning functionality.
665+
* 3. Fetch from cache and execute (while still planning and caching with pruning)
666+
* - Showcases cache fetches.
667+
* 4. Fetch from cache and execute, except with large start tolerances
668+
* - Showcases fuzzy matching, and the impact of start tolerance.
669+
*/
670+
651671
std::atomic<size_t> demo_phase = 0;
652672
std::atomic<bool> run_execute = false;
653673

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
Fuzzy-Matching Trajectory Cache - Quickstart Guide
2+
==================================================
3+
4+
The fuzzy-matching trajectory cache allows you to insert and fetch manipulator trajectories, keyed fuzzily on ``MotionPlanRequest`` and ``GetCartesianPath`` requests and trajectories.
5+
6+
The cache will work on manipulators with an arbitrary number of joints, across any number of move groups.
7+
Furthermore, the cache supports pruning and ranking of fetched trajectories, with extension points for injecting your own feature keying, cache insert, cache prune and cache sorting logic.
8+
9+
.. raw:: html
10+
11+
<video width="450px" controls="true" autoplay="true" loop="true">
12+
<source src="../../../_static/videos/trajectory_cache/01_cache_and_execute_loop.webm" type="video/webm">
13+
Introduction video showing the trajectory cache working.
14+
</video>
15+
16+
For more info, please see the :moveit_codedir:`package README <moveit_ros/trajectory_cache/README.md>`.
17+
18+
.. warning::
19+
The cache does NOT support collision detection and some other constraints (e.g. multi-DoF joints, planning scene, constraint regions, and visibility constraints)!
20+
21+
Plans will be inserted into and fetched from the cache IGNORING collision and those constraints.
22+
If your planning scene is expected to change significantly between cache lookups, ensure that you validate any fetched plans for collisions.
23+
24+
Quick Example Usage
25+
-------------------
26+
27+
**PRE-REQUISITE**: The ``warehouse_plugin`` ROS parameter must be set to a `warehouse_ros <https://github.com/moveit/warehouse_ros>`_ plugin you have installed, which determines what database backend should be used for the cache.
28+
29+
::
30+
31+
auto cache = std::make_shared<TrajectoryCache>(node);
32+
cache->init(/*db_host=*/":memory:", /*db_port=*/0, /*exact_match_precision=*/1e-6);
33+
34+
auto default_features = TrajectoryCache::getDefaultFeatures(start_tolerance, goal_tolerance);
35+
std::string TrajectoryCache::getDefaultSortFeature(); // Sorts by planned execution time.
36+
37+
move_group.setPoseTarget(...);
38+
moveit_msgs::msg::MotionPlanRequest motion_plan_req_msg;
39+
move_group.constructMotionPlanRequest(motion_plan_request_msg);
40+
41+
auto fetched_trajectory = // Use the cache fetch in place of planning!
42+
cache->fetchBestMatchingTrajectory(*move_group_interface, robot_name, motion_plan_req_msg,
43+
/*features=*/default_features,
44+
/*sort_by=*/TrajectoryCache::getDefaultSortFeature(),
45+
/*ascending=*/true);
46+
47+
if (fetched_trajectory) // Great! We got a cache hit, we can execute it.
48+
{
49+
move_group.execute(*fetched_trajectory);
50+
}
51+
else // Otherwise, plan... And put it for posterity!
52+
{
53+
moveit::planning_interface::MoveGroupInterface::Plan plan;
54+
if (move_group.plan(plan) == moveit::core::MoveItErrorCode::SUCCESS)
55+
{
56+
cache->insertTrajectory(
57+
*interface, robot_name, std::move(plan_req_msg), std::move(plan),
58+
/*cache_insert_policy=*/BestSeenExecutionTimePolicy(),
59+
/*prune_worse_trajectories=*/true, /*additional_features=*/{});
60+
}
61+
}
62+
63+
Cartesian variants of the methods in the above example exist.
64+
65+
For more information, please read the extensive API documentation for :cpp_api:`moveit_ros::trajectory_cache::TrajectoryCache`.
66+
67+
Why A Cache?
68+
------------
69+
70+
A trajectory cache helps:
71+
72+
- Cut down on planning time
73+
- Allows for consistent predictable behavior of used together with a stochastic planner
74+
75+
- It effectively allows you to "freeze" a move
76+
77+
To explain this, consider that planners in MoveIt generally fall under two main camps: stochastic/probabilistic, and optimization based.
78+
The probabilistic planners are fast, but usually non-deterministic, whereas the optimization based ones are usually slow, but deterministic.
79+
80+
One way to get around this is to pre-plan and manually select and label robot trajectories to "freeze" in a trajectory database to then replay by name, which avoids needing to spend time to replan, and allows you to ensure that motions are constant and repeatable.
81+
However, this approach is not very flexible and not easily reused.
82+
83+
The trajectory cache improves upon this approach by allowing a user to "freeze" and store successful plans, but **also** look up those plans in a more generalizable and natural way, using the planning request itself to key the cache, effectively allowing the cache to stand in for a planning call.
84+
85+
Furthermore, the specific properties of this trajectory cache provides further unique benefits:
86+
87+
1. With fuzzy matching, "frozen" plans are much easier to look up and reuse, while simultaneously increasing the chances of a cache hit.
88+
2. The ability to rank trajectories will, if used with a stochastic planner over sufficient runs, cause the cache to eventually converge to increasingly optimal plans.
89+
90+
Finally, the cache makes use of pruning to optimize fetch times, and also finds ways to "canonicalize" features of the keying request to increase chances of a cache hit.
91+
92+
Working Principle
93+
-----------------
94+
If a plan request has features (e.g., start, goal, and constraint conditions) that are "close enough" to an entry in the cache, then the cached trajectory should be reusable for that request, allowing us to skip planning.
95+
96+
The cache extracts these features from the planning request and plan response, storing them in the cache database.
97+
When a new planning request is used to attempt to fetch a matching plan, the cache attempts to fuzzily match the request to pre-existing cache entries keyed on similar requests.
98+
Any "close enough" matches are then returned as valid cache hits for plan reuse, with the definition of "close enough" depending on the type of feature that is being extracted.
99+
100+
For more information about how the cache works and what specific features are used to key cache entries with, please see the :moveit_codedir:`package README <moveit_ros/trajectory_cache/README.md>` and the extensive API documentation for :cpp_api:`moveit_ros::trajectory_cache::TrajectoryCache` and its related classes.
101+
102+
Demo
103+
----
104+
105+
.. raw:: html
106+
107+
<video width="700px" controls="true" autoplay="true" loop="true">
108+
<source src="../../../_static/videos/trajectory_cache/02_trajectory_cache_demo.webm" type="video/webm">
109+
Trajectory cache demo.
110+
</video>
111+
112+
(Video is 4x speed.)
113+
114+
This demo has four phases that can be advanced using the ``rviz_visual_tools`` dialog box, which combined, showcases the highlights of the cache's capabilities.
115+
116+
1. Plan and cache (no pruning)
117+
2. Plan and cache (with pruning)
118+
3. Fetch from cache and execute (while still planning and caching with pruning)
119+
4. Fetch from cache and execute, except with large start tolerances
120+
121+
Additionally, the `demo source code itself <how_to_guides/trajectory_cache/src/trajectory_cache_demo.cpp>`_ is heavily annotated with comments and tutorial notes, should you wish to inspect the code and dive deeper.
122+
123+
Pre-Requisites
124+
++++++++++++++
125+
126+
Make sure you have built the `moveit2_tutorials <https://github.com/moveit/moveit2_tutorials>`_ package and sourced the workspace it is built in to ensure that you can run the demo.
127+
128+
Running the Demo
129+
++++++++++++++++
130+
131+
In one terminal, start the move group:
132+
133+
::
134+
135+
ros2 launch moveit2_tutorials trajectory_cache_move_group.launch.py
136+
137+
In another, launch the demo:
138+
139+
::
140+
141+
ros2 launch moveit2_tutorials trajectory_cache_demo.launch.py
142+
143+
You should see something similar to the video, except with a different set of randomly generated goal poses.
144+
145+
Click ``next`` on the rviz window to advance the demo.
146+
147+
.. note::
148+
Sometimes a randomly generated demo goal pose is unreachable (or the ``move_group`` fails to initialize properly).
149+
If this happens, the demo will halt in the first phase due to a failed planning call or other issue.
150+
151+
Just restart the demo, which will generate new demo goal poses, and resolve the issue.
152+
153+
Configuring the Demo
154+
++++++++++++++++++++
155+
156+
Additionally, the demo's launch file exposes launch arguments that allows you to change many aspects of the demo.
157+
Look at the `demo's launch file <how_to_guides/trajectory_cache/launch/trajectory_cache_demo.launch.py>`_ for the full list of configurable launch arguments.
158+
159+
For example, you can specify a disk path for the cache to be saved to and loaded from, instead of memory:
160+
161+
::
162+
163+
ros2 launch moveit2_tutorials trajectory_cache_demo.launch.py cache_db_host:="<some_directory>/trajectory_cache_demo.db
164+
165+
Then, since the demo uses SQLite by default, you can inspect the cache database using an `SQLite database browser <https://sqlitebrowser.org/>`_.
166+
167+
1. CacheNoPruning
168+
+++++++++++++++++
169+
170+
The first phase of the demo shows cache insertion and fetching functionality from a single starting point to multiple goal poses, with no pruning.
171+
172+
The text on the top-left contains the name of the demo phase, and useful information about the state of the cache.
173+
174+
.. image:: images/01_no_pruning_title_and_statistics.png
175+
:width: 400px
176+
177+
In this phase, we are running the planner multiple times per goal, and attempting a cache insert each time.
178+
We also fetch and visualize all matching plans for a particular goal, and also the best matching plan.
179+
180+
To interpret the visualization:
181+
182+
- The **translucent dark grey** trajectory lines are the **planned trajectories** for the current goal
183+
- The **white** trajectory lines are the **trajectories in the cache**
184+
- The **yellow** trajectory lines are the **matching cached trajectories** for the start condition and planning request
185+
- The **green** trajectory line is the **best matching cached trajectory** (in terms of execution time) for the given start condition and planning request
186+
187+
.. image:: images/02_no_pruning_cache_visualization.png
188+
:width: 450px
189+
190+
The default cache insert policy being used inserts a cache plan only if they are the best seen (in terms of execution time) so far.
191+
This is the reason why not every planned trajectory appears to be inserted in the cache.
192+
193+
You should find that the number of cached plans stabilizes over time as the cache saves better and better plans over time.
194+
195+
Leave the demo phase to run for a while to fill up the cache, then hit ``next`` on the ``rviz_visual_tools`` dialogue box to progress the demo to the next phase, where we will prune less optimal cache entries.
196+
197+
2. CacheWithPruning
198+
+++++++++++++++++++
199+
200+
The seconds phase of the demo shows cache insertion and fetching functionality from a single starting point to multiple goal poses, with pruning.
201+
202+
Cache pruning is recommended to keep the number of trajectories in the cache low, saving on cache database storage, and making cache fetches more efficient.
203+
204+
.. image:: images/03_pruning_title_and_statistics.png
205+
:width: 400px
206+
207+
You should also see the ``delete_worse_trajectories`` parameter get set to ``true``.
208+
209+
.. image:: images/04_pruning_delete_worse_trajectories.png
210+
:width: 400px
211+
212+
Immediately, as plans continue to happen, you should see the cache entries get progressively pruned from the cache until eventually, the cache converges to one "best" trajectory per goal.
213+
214+
.. image:: images/05_pruning_cache_visualization.png
215+
:width: 700px
216+
217+
The reason why it takes multiple planning runs to cause the cache to converge, is because we are only attempting to insert plans that have been obtained from the current planning run.
218+
The cache only prunes exactly matching cache entries that are worse than (by default, in terms of execution time) the current insertion candidate.
219+
So, in order for a plan to get pruned, the planned trajectory has to be better than it.
220+
221+
.. note::
222+
If you wanted to immediately prune all worse plans, you could fetch the best plan, then re-insert it to trigger a prune that would achieve that.
223+
224+
Hit ``next`` on the ``rviz_visual_tools`` dialogue box to progress the demo to the next phase, where we will start execution.
225+
226+
3. ExecuteWithCache
227+
+++++++++++++++++++
228+
229+
The third phase of the demo begins execution.
230+
We still plan and cache, but now we also start planning and caching cartesian plans too.
231+
232+
asajdhajksdhlaksdh
233+
234+
cache insertion and fetching functionality from a single starting point to multiple goal poses, with pruning.
235+
236+
237+
4. HighStartTolerance
238+
+++++++++++++++++++++

0 commit comments

Comments
 (0)