A global planner helps a robot find the best path from start to goal on a map. It uses smart algorithms like A* or Dijkstra to avoid obstacles and reach the destination efficiently.
Global planner (A*, Dijkstra) in ROS
class GlobalPlanner: def __init__(self, costmap): self.costmap = costmap def plan(self, start, goal): # Implement A* or Dijkstra algorithm here pass
The planner class needs a costmap that shows obstacles and free space.
The plan method takes start and goal positions and returns a path.
def dijkstra(self, start, goal): # Initialize distances and priority queue # Explore nodes with lowest cost first # Update distances and parents # Return path when goal reached
def a_star(self, start, goal): # Use a heuristic to estimate distance to goal # Explore nodes with lowest cost + heuristic # Update distances and parents # Return path when goal reached
def plan(self, start, goal): if use_a_star: return self.a_star(start, goal) else: return self.dijkstra(start, goal)
This program creates a simple 5x5 grid map with some obstacles. It defines a GlobalPlanner class that can find paths using Dijkstra or A* algorithms. The planner checks neighbors, calculates costs, and reconstructs the path. It prints the map and the paths found by both algorithms.
import heapq class GlobalPlanner: def __init__(self, costmap): self.costmap = costmap self.width = len(costmap[0]) self.height = len(costmap) def neighbors(self, node): x, y = node results = [] for dx, dy in [(-1,0),(1,0),(0,-1),(0,1)]: nx, ny = x + dx, y + dy if 0 <= nx < self.width and 0 <= ny < self.height: if self.costmap[ny][nx] == 0: # 0 means free space results.append((nx, ny)) return results def dijkstra(self, start, goal): dist = {start: 0} prev = {} queue = [(0, start)] while queue: current_dist, current_node = heapq.heappop(queue) if current_node == goal: break for neighbor in self.neighbors(current_node): alt = current_dist + 1 # cost between neighbors is 1 if alt < dist.get(neighbor, float('inf')): dist[neighbor] = alt prev[neighbor] = current_node heapq.heappush(queue, (alt, neighbor)) path = [] node = goal while node != start: path.append(node) node = prev.get(node) if node is None: return [] # no path path.append(start) path.reverse() return path def a_star(self, start, goal): def heuristic(a, b): return abs(a[0] - b[0]) + abs(a[1] - b[1]) dist = {start: 0} prev = {} queue = [(heuristic(start, goal), start)] while queue: current_f, current_node = heapq.heappop(queue) if current_node == goal: break for neighbor in self.neighbors(current_node): tentative_g = dist[current_node] + 1 if tentative_g < dist.get(neighbor, float('inf')): dist[neighbor] = tentative_g prev[neighbor] = current_node f = tentative_g + heuristic(neighbor, goal) heapq.heappush(queue, (f, neighbor)) path = [] node = goal while node != start: path.append(node) node = prev.get(node) if node is None: return [] # no path path.append(start) path.reverse() return path def plan(self, start, goal, use_a_star=True): if use_a_star: return self.a_star(start, goal) else: return self.dijkstra(start, goal) # Example costmap: 0 = free, 1 = obstacle costmap = [ [0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 0, 0, 1, 0], [0, 1, 0, 0, 0], [0, 0, 0, 1, 0], ] planner = GlobalPlanner(costmap) start = (0, 0) goal = (4, 4) print("Costmap:") for row in costmap: print(row) print(f"\nPlanning path from {start} to {goal} using Dijkstra:") path_dijkstra = planner.plan(start, goal, use_a_star=False) print(path_dijkstra) print(f"\nPlanning path from {start} to {goal} using A*:") path_a_star = planner.plan(start, goal, use_a_star=True) print(path_a_star)
Both A* and Dijkstra have time complexity O(E + V log V), where E is edges and V is nodes.
Space complexity depends on map size and data stored for nodes.
Common mistake: forgetting to check if neighbors are inside map and free space.
Use Dijkstra when no heuristic is available; use A* when you can estimate distance to goal for faster search.
Global planners find paths on maps avoiding obstacles.
Dijkstra explores all paths evenly; A* uses a heuristic to speed up search.
Both return a list of points from start to goal for the robot to follow.
Practice
Solution
Step 1: Understand Dijkstra's algorithm behavior
Dijkstra explores all possible paths evenly without using heuristics, ensuring the shortest path but potentially slower.Step 2: Understand A* algorithm behavior
A* uses a heuristic function to estimate the cost to the goal, guiding the search more efficiently and often faster.Final Answer:
A* uses a heuristic to guide the search, while Dijkstra explores all paths evenly. -> Option BQuick Check:
Heuristic guides A*; Dijkstra explores evenly [OK]
- Confusing which algorithm uses heuristics
- Thinking both ignore obstacles
- Assuming both explore paths the same way
Solution
Step 1: Understand object initialization in modern C++
Using 'auto' with direct initialization calls the constructor properly and manages type automatically.Step 2: Analyze each option
auto planner = new DijkstraPlanner(); uses 'new' which returns a pointer, not an object. DijkstraPlanner planner = new DijkstraPlanner(); attempts to assign a pointer to an object, causing a type mismatch compile error. DijkstraPlanner planner(); is a function declaration, not an object. auto planner = DijkstraPlanner(); correctly initializes an object with automatic type deduction.Final Answer:
auto planner = DijkstraPlanner(); -> Option CQuick Check:
Use auto with constructor for clean initialization [OK]
- Using parentheses that declare a function, not an object
- Using 'new' without managing pointers
- Not using auto for type deduction
std::vector<Point> path = planner.makePlan(start, goal); std::cout << path.size() << std::endl;If the planner finds a path with 5 points, what will be printed?
Solution
Step 1: Understand the return value of makePlan()
The makePlan function returns a vector of points representing the path from start to goal, including both points.Step 2: Analyze the output of path.size()
If the planner finds a path with 5 points, the vector size is 5, so printing path.size() outputs 5.Final Answer:
5 -> Option DQuick Check:
Path points count equals vector size [OK]
- Assuming path size excludes start or goal
- Confusing index with size
- Thinking path size counts edges, not points
std::vector<Point> path = planner.makePlan(start, goal);
for (int i = 0; i <= path.size(); i++) {
std::cout << path[i].x << "," << path[i].y << std::endl;
}
What is the error in this code?Solution
Step 1: Analyze the loop condition
The loop runs from i = 0 to i <= path.size(), which means it tries to access path[path.size()] on the last iteration.Step 2: Understand vector indexing
Vectors are zero-indexed, so valid indices are 0 to path.size() - 1. Accessing path[path.size()] causes out-of-bounds error.Final Answer:
Using <= in the loop causes out-of-bounds access. -> Option AQuick Check:
Loop index must be less than size, not less or equal [OK]
- Using <= instead of < in loops
- Confusing vector size with last index
- Assuming makePlan returns empty vector
Solution
Step 1: Understand heuristic modification goal
To prefer paths farther from obstacles, the heuristic should favor those points by lowering their cost or penalizing points near obstacles.Step 2: Analyze penalty application
Adding a penalty to the heuristic cost for points near obstacles increases their cost, which discourages paths near obstacles, as desired for safety.Step 3: Choose correct approach
Add a penalty to the heuristic cost for points near obstacles. correctly adds a penalty to points near obstacles, increasing their heuristic cost and discouraging proximity for safer paths.Final Answer:
Add a penalty to the heuristic cost for points near obstacles. -> Option AQuick Check:
Modify heuristic cost to prefer points near obstacles [OK]
- Confusing penalty direction for heuristic
- Ignoring heuristic and switching algorithms unnecessarily
- Not understanding heuristic impact on path choice
Ready to prove it?
Pass the test and this pattern moves unknown
