> ## Índice de la documentación
> Consulta el índice completo de la documentación en: https://developer.rhombus.com/llms.txt
> Úsalo para descubrir todas las páginas disponibles antes de seguir explorando.

# Mapas y puntos de ruta de Recon

> Trabaja con el mapa de un robot Recon a través de la API: encuentra el mapa asignado, dibújalo con la posición del robot y las zonas de exclusión, convierte entre píxeles de la imagen y coordenadas del mapa, y guarda puntos de ruta para las rutas.

> **Note**: Esta página se tradujo automáticamente. Si encuentras errores o tienes sugerencias, [escríbenos](mailto:support@rhombus.com).

Todo lo que hace un robot ocurre en su mapa: las poses, los puntos de ruta y las rutas son coordenadas en el sistema de coordenadas del mapa. Esta guía lee el mapa, lo dibuja y coloca puntos de ruta en él. Los ejemplos usan la función auxiliar `robot_api` de la [descripción general](https://developer.rhombus.com/es/robots/overview#convenciones).

**Necesitas** una clave de API con acceso de solo lectura a la ubicación del robot para leer el mapa, y acceso de administrador a esa ubicación para guardar puntos de ruta.

## Encuentra el mapa del robot

El robot crea su mapa durante la configuración, y cada robot tiene un mapa asignado. [`getMapAssignment`](https://developer.rhombus.com/api-reference/robot-webservice/retrieve-the-robots-map-assignment-record) lo devuelve:

```python Python
assignment = robot_api("getMapAssignment", {"deviceUuid": ROBOT_UUID})
map_meta = assignment.get("mapMeta")
if not map_meta:
    raise SystemExit("This robot has no assigned map yet")
MAP_UUID = map_meta["uuid"]
keepouts = [f for f in assignment.get("mapFilters", []) if f["type"] == "KEEPOUT"]
```

- `mapMeta` describe el mapa: `uuid`, `locationUuid`, `resolution`, `origin` y, cuando el mapa está colocado sobre un plano de planta, `floorPlan`.
- `mapFilters` enumera las zonas de exclusión aplicadas en este mapa ([abajo](https://developer.rhombus.com/es/robots/maps-and-waypoints#zonas-de-exclusión)).
- Un robot sin mapa asignado no devuelve ninguno de los dos. Las rutas y las patrullas necesitan uno.

Para listar todos los mapas de una ubicación, por ejemplo para elegir uno antes de crear puntos de ruta, llama a [`findMaps`](https://developer.rhombus.com/api-reference/robot-webservice/retrieve-the-list-of-available-robot-maps) con un `locationUuid` (o sin él, para toda la organización).

## Dibuja el mapa

[`getMapImage`](https://developer.rhombus.com/api-reference/robot-webservice/robots-map-image) devuelve el mapa asignado del robot como una imagen **PGM** en escala de grises (`image/x-portable-graymap`): el espacio ocupado en oscuro y el espacio libre en claro. La mayoría de las bibliotecas de imágenes leen PGM:

```python Python
import io
from PIL import Image

response = requests.post(f"{API}/getMapImage", headers=HEADERS, json={"deviceUuid": ROBOT_UUID}, timeout=60)
response.raise_for_status()
map_image = Image.open(io.BytesIO(response.content)).convert("RGB")
map_image.save("map.png")
```

Un robot sin mapa asignado responde `404`.

### Píxeles y coordenadas del mapa

[`getMapMeta`](https://developer.rhombus.com/api-reference/robot-webservice/get-the-robots-map-meta-data) devuelve los dos valores que relacionan la imagen con las coordenadas del mapa:

- `resolution`: metros por píxel.
- `origin`: la posición en el mapa de la esquina inferior izquierda de la imagen. Usa sus dos primeros valores, `x` e `y`.

Las filas de la imagen se cuentan de arriba hacia abajo, mientras que la `y` del mapa crece hacia arriba:

```python Python
meta = robot_api("getMapMeta", {"deviceUuid": ROBOT_UUID})
RES = meta["resolution"]
OX, OY = meta["origin"][0], meta["origin"][1]
HEIGHT = map_image.height

def map_to_pixel(x, y):
    return (x - OX) / RES, HEIGHT - (y - OY) / RES

def pixel_to_map(px, py):
    return px * RES + OX, (HEIGHT - py) * RES + OY
```

Para mostrar dónde está el robot y hacia dónde va, lee `pose`, `goalPose` y `navPath` (su trayecto planificado, una lista de puntos `[x, y, z]`) de [`getFullState`](https://developer.rhombus.com/es/robots/monitor#estado-de-la-flota) y dibújalos con `map_to_pixel`:

```python Python
from PIL import ImageDraw

state = robot_api("getFullState", {"deviceUuid": ROBOT_UUID, "force": False})["fullState"]
draw = ImageDraw.Draw(map_image)
path = [map_to_pixel(p[0], p[1]) for p in state.get("navPath") or []]
if len(path) > 1:
    draw.line(path, fill=(0, 128, 0), width=2)
if state.get("pose"):
    px, py = map_to_pixel(*state["pose"]["position"][:2])
    draw.ellipse([px - 4, py - 4, px + 4, py + 4], fill=(0, 102, 204))
map_image.save("map-with-robot.png")
```

Para mostrar un punto que se mueva con el robot, el [socket en vivo del robot](https://developer.rhombus.com/es/robots/live-socket) transmite la pose a medida que cambia.

## Zonas de exclusión

Una zona de exclusión es un área en la que el robot nunca entra. Cada una de las que aparecen en `mapFilters` tiene un `uuid` y un `name`; [`getMapFilterImage`](https://developer.rhombus.com/api-reference/robot-webservice/robots-map-filter-image) devuelve su máscara, una imagen PGM del mismo tamaño que el mapa:

```python Python
for zone in keepouts:
    response = requests.post(
        f"{API}/getMapFilterImage",
        headers=HEADERS,
        json={"deviceUuid": ROBOT_UUID, "mapFilterUuid": zone["uuid"]},
        timeout=60,
    )
    response.raise_for_status()
    mask = Image.open(io.BytesIO(response.content))
    mask.save(f"keepout-{zone['name']}.png")
```

En la máscara, `0` (negro) es un área en la que el robot nunca entra, `255` (blanco) no tiene efecto, y los valores intermedios son áreas que el robot evita cuando puede. Dibuja los píxeles negros sobre el mapa con un color de advertencia y no coloques puntos de ruta allí.

## Puntos de ruta

Un punto de ruta es una pose con nombre en un mapa. Las paradas de una ruta pueden hacer referencia a un punto de ruta en lugar de repetir su pose, así que varias rutas pueden compartir el mismo lugar.

| Operación                                                                                                          | Cuerpo                                                            |
| ------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------- |
| [`createRobotWaypoint`](https://developer.rhombus.com/api-reference/robot-webservice/create-a-standalone-waypoint) | `mapUuid`, `name`, `pose`                                         |
| [`findRobotWaypointsByMap`](https://developer.rhombus.com/api-reference/robot-webservice/find-waypoints-by-map)    | `mapUuid`                                                         |
| [`getRobotWaypoint`](https://developer.rhombus.com/api-reference/robot-webservice/get-a-waypoint-by-uuid)          | `mapUuid`, `waypointUuid`                                         |
| [`updateRobotWaypoint`](https://developer.rhombus.com/api-reference/robot-webservice/update-a-waypoint)            | `waypointUuid`, y `name` o `pose` (un campo que omitas no cambia) |
| [`deleteRobotWaypoint`](https://developer.rhombus.com/api-reference/robot-webservice/delete-a-waypoint)            | `mapUuid`, `waypointUuid`                                         |

### Guarda el lugar donde está el robot

La pose más fiable es una que el robot ya alcanzó: llévalo hasta el lugar (en la consola o por el [socket en vivo](https://developer.rhombus.com/es/robots/live-socket)) y guarda su pose actual:

```python Python
state = robot_api("getFullState", {"deviceUuid": ROBOT_UUID, "force": False})["fullState"]
waypoint = robot_api("createRobotWaypoint", {
    "mapUuid": state["mapId"],
    "name": "Loading dock door",
    "pose": state["pose"],
})["waypoint"]
print(waypoint["uuid"])
```

### Coloca uno desde el mapa

Para que alguien elija un lugar haciendo clic en la imagen del mapa, convierte el clic con `pixel_to_map` y el rumbo elegido con `heading_to_orientation` de la [descripción general](https://developer.rhombus.com/es/robots/overview#convenciones):

```python Python
import math

x, y = pixel_to_map(412, 238)
waypoint = robot_api("createRobotWaypoint", {
    "mapUuid": MAP_UUID,
    "name": "North fence",
    "pose": {"position": [x, y, 0.0], "orientation": heading_to_orientation(math.pi / 2)},
})["waypoint"]
```

Antes, compara el píxel seleccionado con el mapa y con las máscaras de exclusión: el robot no puede llegar a un punto de ruta que está dentro de una pared o de una zona de exclusión.

### Antes de eliminar uno

Al eliminar un punto de ruta no se revisa si alguna ruta lo usa, y una parada cuyo punto de ruta ya no existe se omite. Busca su `uuid` en el `waypointRefUuid` de las paradas de cada ruta ([`findRobotRoutesByMap`](https://developer.rhombus.com/api-reference/robot-webservice/find-routes-by-map)) y actualiza esas rutas primero.
