ROS 2 Lyrical Luth · Lesson 69 of 86
Path smoothing and constraints
The smoother server, path smoothing algorithms, speed limits and keepout zones.
Estimated time · 60–90 min
Learning goals
What you will understand
- Explain path smoothing and constraints in your own words
- Use it in a small robotics example
- Verify the result instead of assuming it worked
Understand the idea first
The mental model
Grid planners produce paths with sharp corners. A smoother improves them: a simple smoother averages each point with its neighbours (moving average), and Nav2's smoother server offers Simple, Constrained and Savitzky–Golay smoothers. A smoother must keep the path collision-free by checking the costmap.
Constraints shape where the robot may go and how fast: keepout zones (filter mask marking forbidden areas), speed zones (limits in specific regions) and preferred lanes. They use costmap filters, so restrictions apply without changing the planner.
Guided lesson
Work through these steps
- 1.
Source the ROS 2 Lyrical environment in a fresh terminal.
- 2.
Read the path smoothing and constraints example and identify what each line does.
- 3.
Build only the affected package, source the workspace overlay, and run the example.
- 4.
Inspect the result from a second terminal with the ros2 CLI or RViz2 and compare it with the expected result.
Worked example
Read it before you run it
smoother_server:
# Node section.
ros__parameters:
# ROS parameters.
smoother_plugins: ["simple_smoother"]
# Which smoothers to load.
simple_smoother:
# Settings.
plugin: "nav2_smoother::SimpleSmoother"
# Moving-average style smoother.
tolerance: 1.0e-10
# Stop when changes are tiny.
max_its: 1000
# At most this many passes.
do_refinement: true
# Refine the result for extra smoothness.What the example is doing
- 1.The ros2 commands query the running graph; they do not prove that a node's internal behavior is correct.
- 2.Build from the workspace root, then source install/setup.bash so the shell can discover the new package.
- 3.Use a second sourced terminal to inspect nodes and interfaces while the example runs.
Watch it run · Mobile robot
See what this code does
The terminal types this lesson's practice solution and runs it. The scene shows the kind of robot behaviour that code drives. It plays by itself and loops.
Demo for Path smoothing and constraints. Expected result: 0 1.66667 3.33333 5
Practice code
Now type it yourself
Copy the starter into practice.cpp and replace every TODO with your own code. Build and run it: g++ -std=c++17 -Wall -Wextra -Wpedantic practice.cpp -o practice -pthread && ./practice
#include <iostream>
#include <vector>
int main() {
std::vector<double> path{0.0, 1.0, 4.0, 5.0};
std::vector<double> smooth = path;
// TODO: replace each interior point by the average of itself and its two neighbours (use the original path values)
for (std::size_t i = 0; i < smooth.size(); ++i) std::cout << smooth[i] << (i + 1 < smooth.size() ? " " : "\n");
return 0;
}Expected output
0 1.66667 3.33333 5Stuck? Show the full solution (try it yourself first)
#include <iostream>
#include <vector>
int main() {
std::vector<double> path{0.0, 1.0, 4.0, 5.0};
std::vector<double> smooth = path;
for (std::size_t i = 1; i + 1 < path.size(); ++i) smooth[i] = (path[i - 1] + path[i] + path[i + 1]) / 3.0;
for (std::size_t i = 0; i < smooth.size(); ++i) std::cout << smooth[i] << (i + 1 < smooth.size() ? " " : "\n");
return 0;
}Expected result
How you know it worked
- ROS_DISTRO is lyrical in every terminal used for the exercise.
- The complete package from the exercise builds and the expected graph entity appears in a second terminal.
Practical exercise
Apply the lesson
Compare raw and smoothed paths in RViz2, add a keepout zone mask so the robot never enters a marked aisle, and add a speed zone that limits speed to 0.2 m/s near a door.
Before you continue
- ROS_DISTRO reports lyrical in every terminal you used
- The example builds and runs without errors
- You checked the result with a ros2 command, RViz2 or a test, not just by reading the code
If something goes wrong
Source /opt/ros/lyrical/setup.bash, build from the workspace root, then source install/setup.bash in that terminal.
Confirm both terminals use Lyrical, the same ROS_DOMAIN_ID, and compatible network/discovery settings.