> ## Documentation Index
> Fetch the complete documentation index at: https://innateinc-theo-docs-skills-authoring-api.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Navigation Interfaces

export const NavigationUseCasesTable = () => {
  const rows = [{
    scenario: "Go to a saved location",
    recommendation: "Use built-in behavior (agent handles it)."
  }, {
    scenario: "Survey surroundings",
    recommendation: "Create a custom skill with rotate()."
  }, {
    scenario: "Follow a person",
    recommendation: "Create a custom skill with send_cmd_vel()."
  }, {
    scenario: "Fine positioning for manipulation",
    recommendation: "Create a custom skill."
  }, {
    scenario: "Patrol a route",
    recommendation: "Create a custom skill."
  }];
  return <div className="interface-methods-table-wrap">
      <table className="interface-methods-table">
        <thead>
          <tr>
            <th>Scenario</th>
            <th>Recommendation</th>
          </tr>
        </thead>
        <tbody>
          {rows.map(row => <tr key={row.scenario}>
              <td>{row.scenario}</td>
              <td>{row.recommendation}</td>
            </tr>)}
        </tbody>
      </table>
    </div>;
};

export const NavigationInterfaceMethods = () => {
  const rows = [{
    method: "rotate()",
    params: [{
      name: "angle_radians",
      type: "float"
    }],
    desc: "Rotate in place (blocking, uses Nav2)."
  }, {
    method: "send_cmd_vel()",
    params: [{
      name: "linear_x",
      type: "float"
    }, {
      name: "angular_z",
      type: "float"
    }, {
      name: "duration",
      type: "float (seconds)"
    }],
    desc: "Publish velocity commands for duration seconds (non-blocking)."
  }, {
    method: "rotate_in_place()",
    params: [{
      name: "angular_speed",
      type: "float"
    }, {
      name: "duration",
      type: "float (seconds)"
    }],
    desc: "Rotate at a fixed angular speed for a set duration in seconds."
  }, {
    method: "stop()",
    params: [],
    desc: "Stop the base now. Rarely needed — the framework brakes for you at the end of every run and on cancel."
  }, {
    method: "drive()",
    params: [{
      name: "get_xyt",
      type: "callable"
    }, {
      name: "dist",
      type: "float (meters)"
    }],
    desc: "Drive straight by dist, closed on odometry (negative = backwards). Returns True once within tolerance, False on timeout or odometry loss. get_xyt is a zero-arg reader returning (x, y, theta) — build one with the odom_xyt() helper."
  }, {
    method: "rotate_by()",
    params: [{
      name: "get_xyt",
      type: "callable"
    }, {
      name: "angle",
      type: "float (radians)"
    }],
    desc: "Rotate by angle, closed on odometry yaw (positive = counter-clockwise). Same return contract as drive()."
  }];
  return <div className="interface-methods-table-wrap">
      <table className="interface-methods-table">
        <thead>
          <tr>
            <th>Method</th>
            <th>Parameters</th>
            <th>Description</th>
          </tr>
        </thead>
        <tbody>
          {rows.map(row => <tr key={row.method}>
              <td>
                <span className="interface-method-pill">{row.method}</span>
              </td>
              <td>
                {row.params?.length ? <div className="interface-method-params">
                    {row.params.map(param => <span key={`${row.method}-${param.name}`} className="interface-param-badge">
                        {param.name}
                        {param.type ? <span className="interface-param-type">: {param.type}</span> : null}
                      </span>)}
                  </div> : <span className="interface-no-params">None</span>}
              </td>
              <td>{row.desc}</td>
            </tr>)}
        </tbody>
      </table>
    </div>;
};

The `Mobility` interface gives you direct control over the robot base—rotation, velocity commands, and movement. Use it for custom navigation behaviors that complement the built-in navigation.

## Core Navigation (Built-in)

The robot comes with built-in navigation that the agent calls *innately*. You don't need to implement this—it works out of the box.

**Do not modify** the core `navigate_to_position` skill. It's a system-level skill that the agent uses automatically. Modifying it could break navigation behavior.

When you tell the robot "go to the kitchen," the agent automatically:

1. Translates "kitchen" to map coordinates (if the location is saved)

2. Calls the built-in navigation skill

3. Monitors progress and handles obstacles

## Mobility

Declare the interface with a class-level type annotation. Declaring is requiring — the run fails up front if the base is unavailable, so `self.mobility` is guaranteed inside `execute()`:

```innatepy theme={"languages":{"custom":["/languages/python-typed.json"]}}
from innate import Mobility, Skill

class MySkill(Skill):
    mobility: Mobility
```

### Methods

<NavigationInterfaceMethods />

### Examples

```innatepy theme={"languages":{"custom":["/languages/python-typed.json"]}}
import math

# Rotate 90 degrees (blocking)
self.mobility.rotate(math.pi / 2)

# Drive forward for 2 seconds (non-blocking; stops after duration)
self.mobility.send_cmd_vel(linear_x=0.1, angular_z=0.0, duration=2.0)

# Spin in place
self.mobility.rotate_in_place(angular_speed=0.5, duration=3.0)
```

### Closed-loop moves

`send_cmd_vel` is open loop — it commands a speed and hopes. When you need the robot to actually *arrive*, `drive()` and `rotate_by()` watch odometry and correct until they get there:

```innatepy theme={"languages":{"custom":["/languages/python-typed.json"]}}
from innate import Mobility, Odometry, Skill

class NudgeForward(Skill):
    mobility: Mobility
    odom: Odometry

    def guidelines(self) -> str:
        return "Use to shuffle the robot forward a short, precise distance."

    def execute(self):
        # pass a reader; they poll it as they go
        arrived = self.mobility.drive(lambda: self.mobility.odom_xyt(self.odom), 0.25)
        return "Nudged forward" if arrived else "Couldn't get there"
```

`odom_xyt()` turns the odometry feed into the plain `(x, y, theta)` tuple these take.

Both return `True` on arrival and `False` on timeout or lost odometry — they never raise. They stop the base on the way out, whatever happened.

## When to Use

<NavigationUseCasesTable />

## Example: LookAround

A skill that rotates to survey the environment, written with every agent-facing method explicit:

```innatepy theme={"languages":{"custom":["/languages/python-typed.json"]}}
import math
from innate import Mobility, Skill, SkillReturn

class LookAround(Skill):
    mobility: Mobility

    def guidelines(self) -> str:
        return "Use when the robot needs to look in multiple directions."

    def execute(self, num_directions: int = 4) -> SkillReturn:
        rotation_per_step = (2 * math.pi) / num_directions

        for i in range(num_directions):
            self.feedback(f"Looking direction {i + 1}/{num_directions}")
            self.mobility.rotate(rotation_per_step)
            self.sleep(0.2)

        return "Survey complete"
```

Cancellation needs no plumbing: `self.sleep()` raises the moment the user or agent interrupts, the base is braked for you, and the run reports `CANCELLED`.
