CodeTheRobot

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. 1.

    Source the ROS 2 Lyrical environment in a fresh terminal.

  2. 2.

    Read the path smoothing and constraints example and identify what each line does.

  3. 3.

    Build only the affected package, source the workspace overlay, and run the example.

  4. 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. 1.The ros2 commands query the running graph; they do not prove that a node's internal behavior is correct.
  2. 2.Build from the workspace root, then source install/setup.bash so the shell can discover the new package.
  3. 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.

goalMOBILE ROBOT

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 5
Stuck? 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

ros2 cannot find a package or executable.

Source /opt/ros/lyrical/setup.bash, build from the workspace root, then source install/setup.bash in that terminal.

Nodes run but cannot discover each other.

Confirm both terminals use Lyrical, the same ROS_DOMAIN_ID, and compatible network/discovery settings.