Simple navigationΒΆ

Run this example first in the SLAM β†’ localization walkthrough. It lists navigation configs that support SLAM, starts the navigation engine, builds up the map, navigates to a target pose, then saves the map as example-map for Localization with a saved map.

Pass on_feedback / onFeedback to receive NavigationFeedback updates. Each callback includes distance_remaining (distanceRemaining in TypeScript), navigation_time, number_of_recoveries, and current_pose.

"""SLAM navigation example β€” saves example-map for navigation-localization."""

import math
import time

from olo import Client
from olo.locomotion import PlanarMotion
from olo.navigation import Nav2ErrorCode, NavigationFeedback
from olo.platform import NavigationMode, NavigationObservedState
from olo.spatial import Pose

EXAMPLE_MAP_NAME = "example-map"


def on_feedback(feedback: NavigationFeedback) -> None:
    # Do something with the feedback
    pass


with Client() as client:
    configs = client.platform.navigation.get_configs(NavigationMode.SLAM)
    if not configs:
        raise RuntimeError("No navigation configs support SLAM mode")
    config = configs[0]
    print(f"Using navigation config: {config.name = }, {config.id = }")

    # Start navigation engine (namespace resolves like client.robot())
    client.platform.navigation.start(mode=NavigationMode.SLAM, config_id=config.id)
    last_state = None
    deadline = time.time() + 60
    while time.time() < deadline:
        info = client.platform.navigation.deployment()
        state = info.observed.state if info.observed else None
        if state != last_state:
            print(f"Navigation engine: {state}")
            last_state = state
        if state == NavigationObservedState.READY:
            break
        if state == NavigationObservedState.FAILED:
            raise RuntimeError(f"Navigation failed to launch: {info.observed.error_message}")
        time.sleep(2)
    else:
        raise TimeoutError(f"Navigation engine did not become ready within 60s (last state: {last_state})")

    # Move the robot to build a map
    robot = client.robot()
    robot.locomotion.move(PlanarMotion(x=1.0, yaw=2 * math.pi))

    # Once the map has some substance, send the robot a pose goal
    target = Pose.from_xy_yaw(1.5, 0.5, 1.5708)
    result = robot.navigation.navigate_to(target, on_feedback=on_feedback)
    print(f"Navigation outcome: {result.outcome.value} ({result.reason})")
    if result.nav2_error_code:
        print(f"Error: {Nav2ErrorCode.name_for(result.nav2_error_code)}")

    # Persist the SLAM map for reuse
    saved = client.platform.navigation.save_map(EXAMPLE_MAP_NAME)
    print(f"Saved map: {saved.name} [{saved.id}]")
/** SLAM navigation example β€” saves `example-map` for navigation-localization.ts. */

import { connect } from "olo/web";
import { nav2ErrorCodeName, type NavigationFeedback } from "olo/navigation";
import { Pose } from "olo/spatial";

const EXAMPLE_MAP_NAME = "example-map";

function onFeedback(_feedback: NavigationFeedback): void {
  // Do something with the feedback
}

const client = connect();

const configs = await client.platform.navigation.getConfigs("slam");
if (configs.length === 0) {
  throw new Error("No navigation configs support SLAM mode");
}
const config = configs[0];
console.log(`Using navigation config: name=${config.name}, id=${config.id}`);

// Start navigation engine (namespace resolves like client.robot())
await client.platform.navigation.start({
  mode: "slam",
  configId: config.id,
});
let lastState: string | undefined;
const deadline = Date.now() + 60_000;
while (Date.now() < deadline) {
  const info = await client.platform.navigation.deployment();
  const state = info.observed?.state;
  if (state !== lastState) {
    console.log(`Navigation engine: ${state}`);
    lastState = state;
  }
  if (state === "ready") break;
  if (state === "failed") {
    throw new Error(`Navigation failed to launch: ${info.observed?.errorMessage}`);
  }
  await new Promise((r) => setTimeout(r, 2000));
}
if (lastState !== "ready") {
  throw new Error(`Navigation engine did not become ready within 60s (last state: ${lastState})`);
}

// Move the robot to build a map
const robot = await client.robot();
await robot.locomotion.move({ x: 1.0, y: 0, yaw: 2 * Math.PI });

// Once the map has some substance, send the robot a pose goal
const target = Pose.fromXyYaw(1.5, 0.5, 1.5708);
const result = await robot.navigation.navigateTo(target, { onFeedback });
console.log(`Navigation outcome: ${result.outcome} (${result.reason})`);
if (result.nav2ErrorCode) {
  console.log(`Error: ${nav2ErrorCodeName(result.nav2ErrorCode)}`);
}

// Persist the SLAM map for reuse
const saved = await client.platform.navigation.saveMap(EXAMPLE_MAP_NAME);
console.log(`Saved map: ${saved.name} [${saved.id}]`);