Skip to main content
ClaudeWave
Instalar en Claude Code
Copiar
git clone --depth 1 https://github.com/harunkurtdev/ros2-claude-code-template /tmp/nav2_costmap && cp -r /tmp/nav2_costmap/.claude/skills/nav2_costmap ~/.claude/skills/nav2_costmap
Después abre una sesión nueva de Claude Code; el skill carga automáticamente.

SKILL.md

# Nav2 Costmap2D

Source: `~/nav2_ws/src/navigation2/nav2_costmap_2d/`

## Architecture

```
Costmap2DROS (LifecycleNode)
  └── LayeredCostmap
        ├── Plugin Layers (combined into master costmap)
        │   ├── StaticLayer
        │   ├── ObstacleLayer / VoxelLayer
        │   ├── InflationLayer
        │   ├── RangeSensorLayer
        │   └── DenoiseLayer
        └── Filter Layers (post-processing)
            ├── KeepoutFilter
            ├── SpeedFilter
            └── BinaryFilter
```

### Update Flow
1. `updateBounds()` on each layer → defines region to update
2. `updateCosts()` on each layer → applies changes to master grid
3. Combination method determines merge: `Overwrite`, `Max`, `MaxWithoutUnknownOverwrite`

## Cost Values

```cpp
// nav2_costmap_2d/cost_values.hpp
FREE_SPACE = 0
// 1-252: Cost gradient (higher = more expensive)
MAX_NON_OBSTACLE = 252
INSCRIBED_INFLATED_OBSTACLE = 253
LETHAL_OBSTACLE = 254
NO_INFORMATION = 255  // Unknown
```

## Core Classes

### Costmap2D
Main 2D grid. Key methods:
- `getCost(mx, my)` / `setCost(mx, my, cost)` - Cell access
- `worldToMap(wx, wy, mx, my)` / `mapToWorld(mx, my, wx, wy)` - Coordinate conversion
- `getSizeInCellsX()`, `getSizeInCellsY()`, `getResolution()`
- `setConvexPolygonCost(polygon, cost)` - Fill polygon with cost
- `updateOrigin(new_ox, new_oy)` - For rolling window

### Costmap2DROS (ROS Wrapper)
Lifecycle node managing layers, footprint, TF. Key features:
- Dynamic plugin loading via pluginlib
- Footprint publishing and updates
- Costmap publishing for visualization
- Clear costmap services

### Layer (Plugin Interface)
```cpp
class Layer {
  virtual void onInitialize() = 0;
  virtual void updateBounds(robot_x, robot_y, robot_yaw,
    min_x, min_y, max_x, max_y) = 0;
  virtual void updateCosts(master_grid, min_x, min_y, max_x, max_y) = 0;
  virtual void reset() = 0;
  virtual bool isClearable() = 0;
  virtual void activate() = 0;
  virtual void deactivate() = 0;
};
```

### FootprintCollisionChecker
```cpp
template<typename CostmapT>
class FootprintCollisionChecker {
  double footprintCost(const Footprint & footprint);
  double footprintCostAtPose(x, y, theta, footprint);
  double lineCost(x0, x1, y0, y1);
  double pointCost(x, y);
};
```

---

## Layer Plugins

### 1. StaticLayer

**Plugin:** `nav2_costmap_2d::StaticLayer`
**Purpose:** Load occupancy grid from map server (SLAM output)
**Clearable:** No

```yaml
static_layer:
  plugin: "nav2_costmap_2d::StaticLayer"
  map_subscribe_transient_local: true
  map_topic: "/map"
  subscribe_to_updates: false
  track_unknown_space: true
  use_maximum: false
  lethal_threshold: 100
  unknown_cost_value: -1
  trinary_costmap: true
```

### 2. ObstacleLayer

**Plugin:** `nav2_costmap_2d::ObstacleLayer`
**Purpose:** Process LaserScan and PointCloud2 for dynamic obstacles
**Clearable:** Yes

Maintains observation buffers for:
- **Marking:** Insert obstacles where sensor detects them
- **Clearing:** Raytrace free space between sensor and obstacle

```yaml
obstacle_layer:
  plugin: "nav2_costmap_2d::ObstacleLayer"
  enabled: true
  observation_sources: scan pointcloud
  scan:
    topic: /scan
    sensor_frame: ""
    observation_persistence: 0.0
    expected_update_rate: 0.0
    data_type: LaserScan
    min_obstacle_height: 0.0
    max_obstacle_height: 2.0
    inf_is_valid: false
    marking: true
    clearing: true
    obstacle_max_range: 2.5
    obstacle_min_range: 0.0
    raytrace_max_range: 3.0
    raytrace_min_range: 0.0
  pointcloud:
    topic: /points
    data_type: PointCloud2
    # Same params as scan...
```

### 3. VoxelLayer

**Plugin:** `nav2_costmap_2d::VoxelLayer`
**Purpose:** 3D obstacle representation (extends ObstacleLayer)
**Clearable:** Yes

Uses `nav2_voxel_grid::VoxelGrid` for 3D tracking. Projects to 2D costmap.

```yaml
voxel_layer:
  plugin: "nav2_costmap_2d::VoxelLayer"
  enabled: true
  # All ObstacleLayer params plus:
  z_voxels: 16          # Vertical resolution
  z_resolution: 0.05    # Voxel height (meters)
  origin_z: 0.0
  mark_threshold: 0     # Min voxels to mark
  unknown_threshold: 15  # Voxels for unknown
  publish_voxel_map: true
```

### 4. InflationLayer

**Plugin:** `nav2_costmap_2d::InflationLayer`
**Purpose:** Expand obstacle costs with exponential decay
**Clearable:** No

Cost function: exponential falloff from lethal obstacles.

```yaml
inflation_layer:
  plugin: "nav2_costmap_2d::InflationLayer"
  cost_scaling_factor: 3.0    # Exponential decay rate
  inflation_radius: 0.55      # Max inflation distance (meters)
  inflate_unknown: false
  inflate_around_unknown: false
```

**Cost formula:**
```
cost = INSCRIBED (253) if distance <= inscribed_radius
cost = exp(-cost_scaling_factor * (distance - inscribed_radius)) * (252 - 1) + 1
```

Higher `cost_scaling_factor` = steeper decay (costs drop faster from obstacles).

### 5. RangeSensorLayer

**Plugin:** `nav2_costmap_2d::RangeSensorLayer`
**Purpose:** IR/Sonar/range sensor integration
**Clearable:** Yes

```yaml
range_layer:
  plugin: "nav2_costmap_2d::RangeSensorLayer"
  topics: ["/sonar0", "/sonar1"]
  input_sensor_type: ALL  # or VARIABLE, FIXED
```

### 6. DenoiseLayer

**Plugin:** `nav2_costmap_2d::DenoiseLayer`
**Purpose:** Filter noise (standalone obstacle pixels or small groups)
**Clearable:** No

```yaml
denoise_layer:
  plugin: "nav2_costmap_2d::DenoiseLayer"
  enabled: true
  minimal_group_size: 2
```

---

## Costmap Filters

Applied as post-processing on combined costmap.

### KeepoutFilter
Enforces no-go zones from filter mask.

```yaml
keepout_filter:
  plugin: "nav2_costmap_2d::KeepoutFilter"
  enabled: true
  filter_info_topic: "/costmap_filter_info"
```

### SpeedFilter
Speed limitations by area from filter mask.

```yaml
speed_filter:
  plugin: "nav2_costmap_2d::SpeedFilter"
  enabled: true
  filter_info_topic: "/costmap_filter_info"
  speed_limit_topic: "/speed_limit"
```

**CostmapFilterInfo message types:**
- `type: 0` → Keepout zone
- `type: 1` → Speed limit (percen
behaviortree-reviewerSubagent

Use proactively before opening a PR that adds or changes BehaviorTree.CPP nodes or BehaviorTree.ROS2 wrappers (RosActionNode/RosServiceNode/RosTopicPub/SubNode, TreeExecutionServer). Reviews a diff against BT.CPP v4 conventions — node base-class choice, non-blocking ticks, ports/blackboard typing, factory/plugin registration, XML v4, and the ROS 2 wrapper contract. Returns a punch list with file:line anchors, not a rewrite.

clean-arch-architectSubagent

Use when a design decision touches Clean Architecture boundaries in a ROS 2 project — which layer a new behaviour belongs to, whether a port belongs in domain or application, whether a new node should be lifecycle-managed, whether to compose nodes or split packages. Returns an architectural recommendation with trade-offs, not implementation.

ecs-architectSubagent

Use when a design decision touches the gz-sim ECS — where new state should live, which system phase should write it, how to avoid coupling, whether to add a component vs. a member variable, whether a new system should be split or merged with an existing one. Returns an architectural recommendation with trade-offs, not implementation.

gz-style-reviewerSubagent

Use proactively before opening any gz-sim PR. Reviews a diff against the project's C++17 style, ECS conventions, plugin registration patterns, CMake structure, test placement, Migration.md / Changelog.md expectations, and pre-commit configuration. Returns a punch list, not a rewrite.

ros2-controllers-reviewerSubagent

Use proactively before opening a PR that adds or changes a ros2_control controller, broadcaster, or hardware component (incl. URDF <ros2_control> bringup). Reviews a diff against ros2_controllers / ros2_control_demos conventions — controller & hardware lifecycle, command/state interface configuration, real-time safety of update()/read()/write(), generate_parameter_library usage, pluginlib registration, chainable-controller correctness, URDF wiring, and tests. Returns a punch list with file:line anchors, not a rewrite.

ros2-style-reviewerSubagent

Use proactively before opening any ROS 2 / Nav 2 PR. Reviews a diff against this template's Clean Architecture, ROS 2 communication, lifecycle, testing, and Nav 2 plugin conventions. Returns a punch list with file:line anchors, not a rewrite.

vda5050-reviewerSubagent

Use proactively before opening a PR that touches a VDA 5050 connector / fleet bridge. Reviews a diff against VDA 5050 v3.0.0 protocol compliance (topics, QoS, header rules, base/horizon, action state machine, schema validation) and the template's Clean Architecture for the MQTT↔Nav 2 bridge. Returns a punch list with file:line anchors, not a rewrite.

buildSlash Command

Build the colcon workspace (optionally a single package) and report the outcome.