Inspect the map and navigate to a reachable goalΒΆ
Queries client.platform.navigation.deployment to confirm navigation is running.Then fetches the occupancy grid and asks the navigation engine whether the goal is planner-reachable before sending a NavigateToPose goal.
from olo import Client
from olo.platform import NavigationObservedState
TARGET_X = 1.0
TARGET_Y = 0.5
with Client() as client:
# Require an already-running Nav2 deployment (start it via navigation-simple
# or the UI). Namespace resolves like client.robot().
info = client.platform.navigation.deployment()
state = info.observed.state if info.observed else None
if state != NavigationObservedState.READY:
raise RuntimeError(
f"Navigation engine is not ready (state={state}); "
"start it first, then re-run this example"
)
print(f"Navigation engine: {state}")
robot = client.robot()
nav = robot.navigation
# Fetch the current occupancy grid
grid = nav.get_map()
print(f"map={grid.width}x{grid.height} resolution={grid.resolution:.2f} m")
# Reject cells outside the map, unexplored, or occupied
cell = grid.world_to_cell(TARGET_X, TARGET_Y)
if not grid.in_bounds(*cell):
raise RuntimeError(f"Target ({TARGET_X}, {TARGET_Y}) is outside the map")
if grid.is_unknown(*cell):
raise RuntimeError(f"Target cell {cell} is unexplored")
if grid.is_occupied(*cell):
raise RuntimeError(f"Target cell {cell} is occupied")
# Ask Nav2 whether the goal is planner-reachable
goal = grid.pose_at(*cell, yaw=0.0)
check = nav.check_reachability(goal)
print(
f"reachable={check.reachable} path_length={check.path_length:.2f} m "
f"reason={check.reason or 'ok'}"
)
if not check.reachable:
raise RuntimeError("Nav2 planner reports the goal is not reachable")
# Send a NavigateToPose goal
result = nav.navigate_to(goal)
print(f"Outcome: {result.outcome.value} ({result.reason})")
import { connect } from "olo/web";
const TARGET_X = 1.0;
const TARGET_Y = 0.5;
const client = connect();
// Require an already-running Nav2 deployment (start it via navigation-simple
// or the UI). Namespace resolves like client.robot().
const info = await client.platform.navigation.deployment();
const state = info.observed?.state;
if (state !== "ready") {
throw new Error(
`Navigation engine is not ready (state=${state}); ` +
"start it first, then re-run this example",
);
}
console.log(`Navigation engine: ${state}`);
const robot = await client.robot();
const nav = robot.navigation;
// Fetch the current occupancy grid
const grid = await nav.getMap();
console.log(`map=${grid.width}x${grid.height} resolution=${grid.resolution.toFixed(2)} m`);
// Reject cells outside the map, unexplored, or occupied
const [cellX, cellY] = grid.worldToCell(TARGET_X, TARGET_Y);
if (!grid.inBounds(cellX, cellY)) {
throw new Error(`Target (${TARGET_X}, ${TARGET_Y}) is outside the map`);
}
if (grid.isUnknown(cellX, cellY)) {
throw new Error(`Target cell (${cellX}, ${cellY}) is unexplored`);
}
if (grid.isOccupied(cellX, cellY)) {
throw new Error(`Target cell (${cellX}, ${cellY}) is occupied`);
}
// Ask Nav2 whether the goal is planner-reachable
const goal = grid.poseAt(cellX, cellY);
const check = await nav.checkReachability(goal);
console.log(
`reachable=${check.reachable} path_length=${check.pathLength.toFixed(2)} m ` +
`reason=${check.reason || "ok"}`,
);
if (!check.reachable) {
throw new Error("Nav2 planner reports the goal is not reachable");
}
// Send a NavigateToPose goal
const result = await nav.navigateTo(goal);
console.log(`Outcome: ${result.outcome} (${result.reason})`);