diff --git a/README.md b/README.md
index 3b3176f..7f99727 100644
--- a/README.md
+++ b/README.md
@@ -2,27 +2,32 @@
Giao diện web quản lý robot: mission, map, dashboard, user, Modbus/REST tích hợp.
-Tài liệu UI/UX và trạng thái tính năng: [`docs/Reference_guide.md`](docs/Reference_guide.md).
+Tài liệu UI/UX và trạng thái tính năng: `[docs/Reference_guide.md](docs/Reference_guide.md)`.
**Backend:** C++ executable `robot_app` (`src/app/robot_app.cpp`, class `RobotApp`).
**Frontend:** static `www/` (vanilla JS).
Chức năng chính:
+
- Đăng ký danh sách cảm biến LiDAR (tên, ip, port)
- Đăng ký IMU (tên, frame_id, topic, nguồn) và pose trên robot
- Kéo thả icon LiDAR/IMU trên canvas để set vị trí (robot frame)
- Nhiều layout — mỗi layout lưu profile trong SQLite (`layout_profiles`); catalog trong document `state`
- Mission editor, map editor, dashboard, transitions, paths, path guides, I/O modules
+
+
## Dữ liệu
-| Thành phần | Vị trí |
-|------------|--------|
-| Database chính | `data/RBS.db` (SQLite, WAL) — auth, users, missions, queue, maps, dashboards, … |
-| Media map | `data/maps/{map_id}/` |
-| Media sound | `data/sounds/{sound_id}/` |
-| Recordings (stub) | `data/recordings/` |
-| Layout catalog | document `state` trong DB + `data/state.json` (legacy) |
+
+| Thành phần | Vị trí |
+| ----------------- | ------------------------------------------------------------------------------- |
+| Database chính | `data/RBS.db` (SQLite, WAL) — auth, users, missions, queue, maps, dashboards, … |
+| Media map | `data/maps/{map_id}/` |
+| Media sound | `data/sounds/{sound_id}/` |
+| Recordings (stub) | `data/recordings/` |
+| Layout catalog | document `state` trong DB + `data/state.json` (legacy) |
+
Lần khởi động đầu, server **import** các file JSON cũ (nếu có) vào SQLite: `auth.json`, `missions.json`, `mission_queue.json`, `robot_runtime.json`.
@@ -62,16 +67,20 @@ Tắt auth cho dev/test:
LM_AUTH_DISABLED=1 ./build/robot_app
```
+
+
## Docker (giới hạn 2 CPU, 4 GB RAM)
Mô phỏng cấu hình controller tối thiểu (Dual-Core, 4 GB) trên máy dev:
-| Mục | Giá trị |
-|-----|---------|
-| Compose service | `robot-app` |
-| Image | `robot-app:RBS` |
-| Container | `robot-app-limited` |
-| Port | `8080` |
+
+| Mục | Giá trị |
+| --------------- | ------------------- |
+| Compose service | `robot-app` |
+| Image | `robot-app:RBS` |
+| Container | `robot-app-limited` |
+| Port | `8080` |
+
```bash
./scripts/lm.sh docker up
@@ -100,69 +109,87 @@ Dữ liệu lưu trên host qua volume `./data:/app/data`.
./scripts/lm.sh docker htop
```
+
+
## Biến môi trường
-| Biến | Mặc định | Mô tả |
-|------|----------|--------|
-| `LM_AUTH_DISABLED` | — | `1` = tắt xác thực API (dev/test) |
-| `LM_URL` | `http://127.0.0.1:8080` | URL khi test container |
-| `LM_CONTAINER` | `robot-app-limited` | Tên container Docker |
-| `LM_TEST_PORT` | `18080` | Port server tạm khi `test run` |
+
+| Biến | Mặc định | Mô tả |
+| ------------------ | ----------------------- | --------------------------------- |
+| `LM_AUTH_DISABLED` | — | `1` = tắt xác thực API (dev/test) |
+| `LM_URL` | `http://127.0.0.1:8080` | URL khi test container |
+| `LM_CONTAINER` | `robot-app-limited` | Tên container Docker |
+| `LM_TEST_PORT` | `18080` | Port server tạm khi `test run` |
+
+
+
## API (tóm tắt)
+
+
### Maps, sounds, dashboards
-| Method | Endpoint | Mô tả |
-|--------|----------|-------|
-| GET/POST | `/api/maps` | Danh sách / tạo map |
-| GET/PUT/DELETE | `/api/maps/{id}` | CRUD map |
-| GET/POST | `/api/maps/{id}/image` | Ảnh map (`data/maps/{id}/`) |
-| GET/POST | `/api/sounds` | Danh sách / tạo sound |
-| GET/PUT/DELETE | `/api/sounds/{id}` | CRUD sound |
-| GET/POST | `/api/sounds/{id}/file` | Upload/tải file âm thanh |
-| POST | `/api/sounds/{id}/play` | Phát trên robot (volume 0–100) |
-| GET/PUT | `/api/dashboards` | Dashboard server-side |
+
+| Method | Endpoint | Mô tả |
+| -------------- | ----------------------- | ------------------------------ |
+| GET/POST | `/api/maps` | Danh sách / tạo map |
+| GET/PUT/DELETE | `/api/maps/{id}` | CRUD map |
+| GET/POST | `/api/maps/{id}/image` | Ảnh map (`data/maps/{id}/`) |
+| GET/POST | `/api/sounds` | Danh sách / tạo sound |
+| GET/PUT/DELETE | `/api/sounds/{id}` | CRUD sound |
+| GET/POST | `/api/sounds/{id}/file` | Upload/tải file âm thanh |
+| POST | `/api/sounds/{id}/play` | Phát trên robot (volume 0–100) |
+| GET/PUT | `/api/dashboards` | Dashboard server-side |
+
+
+
### Missions & queue
-| Method | Endpoint | Mô tả |
-|--------|----------|-------|
-| GET/PUT | `/api/missions` | Danh sách / lưu missions |
-| GET | `/api/mission_queue` | Queue + runner status |
-| POST | `/api/mission_queue` | Enqueue mission |
-| DELETE | `/api/mission_queue` | Xóa toàn bộ queue |
-| DELETE | `/api/mission_queue/{id}` | Xóa một entry |
-| PUT | `/api/mission_queue/reorder` | Sắp xếp lại queue |
-| POST | `/api/mission_queue/pause` | Tạm dừng runner |
-| POST | `/api/mission_queue/continue` | Tiếp tục runner |
-| POST | `/api/mission_queue/cancel` | Hủy mission đang chạy |
+
+| Method | Endpoint | Mô tả |
+| ------- | ----------------------------- | ------------------------ |
+| GET/PUT | `/api/missions` | Danh sách / lưu missions |
+| GET | `/api/mission_queue` | Queue + runner status |
+| POST | `/api/mission_queue` | Enqueue mission |
+| DELETE | `/api/mission_queue` | Xóa toàn bộ queue |
+| DELETE | `/api/mission_queue/{id}` | Xóa một entry |
+| PUT | `/api/mission_queue/reorder` | Sắp xếp lại queue |
+| POST | `/api/mission_queue/pause` | Tạm dừng runner |
+| POST | `/api/mission_queue/continue` | Tiếp tục runner |
+| POST | `/api/mission_queue/cancel` | Hủy mission đang chạy |
+
REST tương thích: `GET/POST/DELETE /api/v2.0.0/mission_queue`
### Transitions, paths, I/O
-| Method | Endpoint | Mô tả |
-|--------|----------|-------|
-| GET/POST | `/api/transitions` | CRUD transition (`?site_id=`) |
-| GET/DELETE | `/api/paths`, `/api/paths/{id}` | Path cache (auto-create; xóa thủ công) |
-| GET/POST/PUT/DELETE | `/api/path_guides` | Path guides |
-| GET/POST/PUT/DELETE | `/api/io_modules` | I/O modules (Bluetooth / WISE) |
-| POST | `/api/io_modules/test` | Kiểm tra kết nối TCP |
+
+| Method | Endpoint | Mô tả |
+| ------------------- | ------------------------------- | -------------------------------------- |
+| GET/POST | `/api/transitions` | CRUD transition (`?site_id=`) |
+| GET/DELETE | `/api/paths`, `/api/paths/{id}` | Path cache (auto-create; xóa thủ công) |
+| GET/POST/PUT/DELETE | `/api/path_guides` | Path guides |
+| GET/POST/PUT/DELETE | `/api/io_modules` | I/O modules (Bluetooth / WISE) |
+| POST | `/api/io_modules/test` | Kiểm tra kết nối TCP |
+
**Transitions:** Setup → Transitions — cấu hình chuyển map (from/to map, start/goal position, mission liên kết). Khi mission chạy `move_to_position` hoặc `adjust_localization` tới position trên map khác `active_map_id`, runner tự chèn: đi tới start position → chạy transition mission → chuyển map → đi tới goal position → tiếp tục bước gốc.
### Robot & tích hợp
-| Method | Endpoint | Mô tả |
-|--------|----------|-------|
-| GET | `/api/robot/status` | Trạng thái robot (pin, pose, mission strip) |
-| POST | `/api/robot/start`, `/api/robot/pause` | Start / pause |
-| POST | `/api/robot/errors/reset` | Xóa lỗi |
-| POST | `/api/robot/active_map` | Đặt map đang hoạt động |
-| GET/POST/DELETE | `/api/triggers` | Modbus mission triggers (coil 1001–2000) |
-| GET/POST/DELETE | `/api/fleet/schedules` | Lịch fleet (stub scheduler) |
-| GET | `/api/recordings` | Stub — trả về `[]` |
+
+| Method | Endpoint | Mô tả |
+| --------------- | -------------------------------------- | ------------------------------------------- |
+| GET | `/api/robot/status` | Trạng thái robot (pin, pose, mission strip) |
+| POST | `/api/robot/start`, `/api/robot/pause` | Start / pause |
+| POST | `/api/robot/errors/reset` | Xóa lỗi |
+| POST | `/api/robot/active_map` | Đặt map đang hoạt động |
+| GET/POST/DELETE | `/api/triggers` | Modbus mission triggers (coil 1001–2000) |
+| GET/POST/DELETE | `/api/fleet/schedules` | Lịch fleet (stub scheduler) |
+| GET | `/api/recordings` | Stub — trả về `[]` |
+
Modbus TCP server: port **5502** (mission triggers + action coils 1–6).
@@ -170,15 +197,17 @@ Modbus TCP server: port **5502** (mission triggers + action coils 1–6).
Trang web **bắt buộc đăng nhập** (password hoặc PIN 4 số). Tài khoản mặc định:
-| User | Password | Nhóm |
-|------|----------|------|
-| Admin | admin | Administrators (full quyền) |
-| User | user | Users (dashboard write, còn lại read) |
-| Distributor | distributor | Distributors (full quyền) |
+
+| User | Password | Nhóm |
+| ----------- | ----------- | ------------------------------------- |
+| Admin | admin | Administrators (full quyền) |
+| User | user | Users (dashboard write, còn lại read) |
+| Distributor | distributor | Distributors (full quyền) |
+
PIN chỉ dùng với nhóm **Users** sau khi admin gán (`PUT /api/users/:id`).
-Chi tiết auth & permissions: [`docs/Reference_guide.md` §2](docs/Reference_guide.md#2-đăng-nhập-và-phân-quyền).
+Chi tiết auth & permissions: `docs/Reference_guide.md` [§2](docs/Reference_guide.md#2-đăng-nhập-và-phân-quyền).
## Test tự động
@@ -214,4 +243,4 @@ Benchmark trong container (cần `docker compose up -d`):
# hoặc: ./scripts/lm.sh bench http
```
-CI: GitHub Actions workflow `.github/workflows/test.yml`.
+CI: GitHub Actions workflow `.github/workflows/test.yml`.
\ No newline at end of file
diff --git a/docs/AMR_SLAM_Thang_May.md b/docs/AMR_SLAM_Thang_May.md
new file mode 100644
index 0000000..e6ad8d7
--- /dev/null
+++ b/docs/AMR_SLAM_Thang_May.md
@@ -0,0 +1,391 @@
+---
+title: "AMR SLAM Đa Tầng Qua Thang Máy"
+subtitle: "Ghi chú nguyên lý và chức năng thang máy"
+author: "RD Odomety"
+date: "10/07/2026"
+lang: vi
+---
+
+# Tổng quan
+
+Tài liệu này tổng hợp nguyên lý điều hướng **AMR (Autonomous Mobile Robot)** sử dụng **SLAM** để di chuyển giữa các tầng thông qua thang máy, và vai trò/chức năng của thang máy trong hệ thống.
+
+Đây là bài toán **điều hướng đa tầng (multi-floor navigation)** — không chỉ là SLAM thuần túy. SLAM giải quyết "robot đang ở đâu trên bản đồ", còn thang máy thêm lớp **điều phối hệ thống tòa nhà + chuyển đổi ngữ cảnh giữa các tầng**.
+
+---
+
+# Phần 1: Nguyên lý AMR SLAM di chuyển qua thang máy
+
+## 1.1 Kiến trúc tổng quan
+
+Các thành phần chính trong hệ thống:
+
+| Thành phần | Vai trò |
+|---|---|
+| **SLAM / Localization** | Định vị trên bản đồ từng tầng |
+| **Global planner** | Lập kế hoạch đường đi xuyên tầng |
+| **Elevator interface** | Gọi thang, mở cửa, giữ cửa, nhận trạng thái |
+| **Mission / State machine** | Điều phối toàn bộ quy trình lên/xuống tầng |
+| **Map management** | Quản lý nhiều bản đồ, chuyển tầng |
+
+Luồng tương tác:
+
+```
+AMR + SLAM → Navigation / Mission → Elevator Manager
+ ↓
+ Elevator Controller / BMS
+ Map Switch / Relocalization
+```
+
+## 1.2 Cách biểu diễn bản đồ đa tầng
+
+### A. Nhiều bản đồ độc lập (phổ biến nhất)
+
+- Mỗi tầng một map riêng (2D occupancy grid hoặc graph).
+- Các map **không nối liên tục về mặt hình học** — chỉ liên kết qua **elevator node**.
+- Ví dụ: `Floor_1.map`, `Floor_2.map`, mỗi map có điểm `elevator_A_in`, `elevator_A_out`.
+
+### B. Một bản đồ 3D / multi-layer
+
+- Một map chứa nhiều "layer" (mỗi layer = một tầng).
+- Phù hợp khi dùng SLAM 3D hoặc hệ thống thương mại (MiR, Omron, Geek+…).
+
+### C. Topological graph (đồ thị)
+
+- **Node** = điểm quan trọng (phòng, thang máy, cửa).
+- **Edge** = đường đi hoặc **kết nối thang máy giữa các tầng**.
+- Global planner chạy trên graph, local planner chạy trên map 2D từng tầng.
+
+## 1.3 Quy trình điển hình (State Machine)
+
+```
+[Tầng nguồn] [Thang máy] [Tầng đích]
+ | | |
+ Navigate --> Wait at door --> Call elevator --> Enter --> Ride -->
+ Align in cabin --> Door close --> Moving --> Door open --> Exit -->
+ Relocalize on new floor --> Navigate to goal
+```
+
+### Các trạng thái chi tiết
+
+1. **Navigate to elevator waiting point** — Robot đi đến vị trí chờ trước cửa thang.
+2. **Request elevator** — Gửi yêu cầu qua API/BMS: tầng đích, ID thang, ưu tiên.
+3. **Wait for arrival** — Chờ thang đến đúng tầng, cửa mở, cabin trống.
+4. **Enter elevator** — Local navigation vào cabin (line following, QR marker, hoặc map nhỏ trong cabin).
+5. **Inside cabin — localization bị "mù"** — Điểm then chốt kỹ thuật (xem mục 1.4).
+6. **Ride to target floor** — Robot đứng yên; hệ thống theo dõi trạng thái thang.
+7. **Exit elevator** — Ra khỏi cabin, đến điểm relocalization đã định sẵn.
+8. **Relocalize on new floor** — Xác định lại vị trí trên map tầng mới.
+9. **Continue mission** — Điều hướng bình thường trên tầng đích.
+
+## 1.4 Thách thức SLAM / Localization trong thang máy
+
+### Vấn đề cốt lõi
+
+Trong cabin, môi trường **thay đổi liên tục** (cửa đóng/mở, cabin di chuyển, người vào ra). LiDAR scan matching dễ **drift** hoặc **nhảy pose sai**.
+
+### Cách xử lý thực tế
+
+| Giai đoạn | Chiến lược |
+|---|---|
+| **Trước khi vào** | Localization bình thường (AMCL, Cartographer, SLAM Toolbox…) |
+| **Trong cabin** | **Tắt hoặc "đóng băng" SLAM**; chỉ dùng odometry ngắn hoặc IMU |
+| **Khi ra cabin** | **Relocalization** bằng scan matching với map tầng mới |
+| **Backup** | QR / AprilTag / UWB tại cửa thang hai đầu |
+
+### Vai trò của Odometry
+
+Trong cabin, **wheel odometry + IMU** giữ ước lượng tương đối ngắn (vài mét). Tuy nhiên odometry **không đủ** để biết đã lên tầng nào — cần **tín hiệu từ thang máy** (floor reached).
+
+Luồng điển hình:
+
+```
+SLAM (tin cậy) → Odom only (trong thang) → SLAM relocalize (tầng mới)
+```
+
+## 1.5 Tích hợp thang máy (Elevator Integration)
+
+### Mức độ tích hợp
+
+**Mức 1 — Passive (đơn giản)**
+
+- Robot chỉ chờ cửa mở (sensor hoặc camera), không điều khiển thang.
+- Phù hợp thang công cộng, khó triển khai công nghiệp.
+
+**Mức 2 — API với BMS / EMS (phổ biến)**
+
+- Giao thức: Modbus, BACnet, OPC-UA, REST API, MQTT.
+- Robot gửi: `call(floor=5)`, `hold_door()`, `release()`.
+- Thang trả: `current_floor`, `door_open`, `moving`, `fault`.
+
+**Mức 3 — Dedicated robot elevator**
+
+- Thang riêng cho robot (Kone, Otis, Schindler có giải pháp robot elevator).
+- Có **robot mode**: giữ cửa lâu hơn, điều khiển từng bước.
+
+### Tín hiệu thường cần
+
+```
+Robot → Elevator: call_floor, destination_floor, hold_door, cancel
+Elevator → Robot: current_floor, door_status, ready, in_service, fault_code
+```
+
+## 1.6 Global planning xuyên tầng
+
+Planner không tính đường liên tục 3D. Thường là **2 tầng lập kế hoạch**:
+
+1. **Topological planner** (đồ thị):
+
+ ```
+ Room_A (F1) → Elevator_1_wait (F1) → [elevator_edge] → Elevator_1_exit (F3) → Room_B (F3)
+ ```
+
+2. **Local planner** (từng tầng): DWA, TEB, Nav2 trên map 2D của tầng đó.
+
+**Elevator edge** là "cạnh ảo": chi phí = thời gian chờ thang + thời gian di chuyển + rủi ro lỗi.
+
+## 1.7 Relocalization khi sang tầng mới
+
+Sau khi ra khỏi thang, robot **không biết chính xác pose** trên map tầng mới (drift trong cabin).
+
+| Phương pháp | Mô tả |
+|---|---|
+| **Scan matching** | So khớp LiDAR với map tầng mới (AMCL global localization) |
+| **Known exit pose** | Điểm ra cố định; initial pose gần đúng |
+| **Fiducial marker** | QR/AprilTag tại cửa thang |
+| **Feature matching** | Đặc trưng quanh khu vực cửa thang |
+
+Quy trình an toàn: robot ra đến **relocalization zone** → dừng → xác nhận pose (confidence > ngưỡng) → mới tiếp tục.
+
+## 1.8 Luồng dữ liệu tổng thể
+
+```
+Mission: "Deliver to Room 502 (Floor 5)"
+ |
+ v
++------------------+
+| Task Scheduler | --> Chọn route: F1 -> Elevator B -> F5
++--------+---------+
+ |
+ +----+----+
+ v v
++--------+ +--------------+
+| Nav2 | | Elevator FSM |
+| (local)| | (call/wait/ |
+| | | enter/exit) |
++---+----+ +------+-------+
+ | |
+ v v
++--------+ +-----------+
+| SLAM / | | Elevator |
+| AMCL | | API/BMS |
++---+----+ +-----------+
+ |
+ v
++----------+
+| Odometry | <- dung khi SLAM khong tin cay (trong cabin)
+| + IMU |
++----------+
+```
+
+## 1.9 Các vấn đề thực tế cần lưu ý
+
+1. **An toàn**: E-stop, phát hiện người trong cabin, không chen khi cửa sắp đóng.
+2. **Đồng bộ thời gian**: Timestamp map, odometry và trạng thái thang phải nhất quán.
+3. **Nhiều robot**: Queue thang, tránh hai robot cùng gọi một cabin.
+4. **Map maintenance**: Thay đổi nội thất từng tầng → cập nhật map riêng.
+5. **Khe cửa thang / ngưỡng**: Robot phải vượt qua được; thường cần map chi tiết vùng cửa.
+6. **Mất mạng**: Timeout khi gọi thang; retry và fallback.
+7. **Chuẩn hóa tọa độ**: Mỗi tầng một hệ tọa độ; chỉ nối qua elevator node, không cộng trực tiếp tọa độ giữa các tầng.
+
+---
+
+# Phần 2: Chức năng thang máy trong điều hướng AMR đa tầng
+
+## 2.1 Vai trò vật lý vs vai trò logic
+
+| Lớp | Thang máy làm gì |
+|---|---|
+| **Vật lý** | Chuyển robot từ tầng A sang tầng B |
+| **Logic (navigation)** | Cạnh nối giữa hai map độc lập (`Floor_A` ↔ `Floor_B`) |
+| **Điều phối** | Tài nguyên dùng chung — nhiều robot có thể tranh nhau |
+| **An toàn** | Vùng nguy hiểm: cửa, khe, cabin chuyển động |
+
+Với SLAM: **thang máy là ranh giới mà localization không còn đáng tin**. Robot "nhảy" từ một không gian định vị được sang không gian khác, còn thang đảm nhiệm phần ở giữa.
+
+## 2.2 Chức năng theo góc nhìn hệ thống
+
+### A. Vận chuyển (Transport)
+
+Chức năng cơ bản: đưa cabin từ tầng nguồn đến tầng đích.
+
+Robot **không tự biết** đã lên tầng nào nếu không có tín hiệu từ thang (`current_floor`, `arrived_at_destination`).
+
+### B. Cửa và vùng truy cập (Access control)
+
+Thang quyết định **khi nào robot được vào/ra**:
+
+- Cửa mở đủ lâu để robot vào (thường cần **hold door**)
+- Cabin dừng đúng tầng, không lệch sàn quá ngưỡng
+- Không đóng cửa khi có vật cản (light curtain, cảm biến cửa)
+
+### C. Đồng bộ với robot (Synchronization)
+
+```
+Robot FSM Elevator FSM
+----------- --------------
+GO_TO_ELEVATOR IDLE
+WAIT_CALL --> RECEIVE_CALL
+WAIT_DOOR_OPEN <-- ARRIVED + DOOR_OPEN
+ENTERING <-> DOOR_HELD
+INSIDE --> GO_TO_DEST_FLOOR
+WAIT_EXIT <-- ARRIVED + DOOR_OPEN
+EXITING <-> DOOR_HELD
+RELOCALIZE RELEASE / IDLE
+```
+
+### D. Tài nguyên dùng chung (Resource management)
+
+- **Queue** yêu cầu
+- **Reservation** (giữ thang cho robot)
+- **Priority** (robot giao hàng vs robot dọn phòng)
+
+## 2.3 Interface: Robot ↔ Thang
+
+### Robot → Thang (Commands)
+
+| Lệnh | Mục đích |
+|---|---|
+| `call_elevator(floor)` | Gọi thang đến tầng robot đang đứng |
+| `request_ride(dest_floor)` | Đặt đích sau khi đã vào cabin |
+| `hold_door()` | Giữ cửa mở khi robot đang vào/ra |
+| `release_door()` | Cho phép đóng cửa |
+| `cancel()` | Hủy khi nhiệm vụ thất bại |
+| `ping / heartbeat` | Giữ session, phát hiện mất kết nối |
+
+### Thang → Robot (Status / Events)
+
+| Tín hiệu | Robot dùng để |
+|---|---|
+| `current_floor` | Biết thang đang ở đâu |
+| `door_open / door_closed` | Quyết định vào/ra |
+| `moving / stopped` | Biết cabin đang chạy hay dừng |
+| `at_destination` | Xác nhận đã đến tầng đích |
+| `ready_for_robot` | Cabin sẵn sàng (trống, không lỗi) |
+| `fault / maintenance` | Dừng mission, chọn thang khác |
+| `passenger_present` | Có người — có thể chờ hoặc hủy |
+
+## 2.4 Các chế độ vận hành thang với robot
+
+| Chế độ | Mô tả |
+|---|---|
+| **Thang công cộng** | Robot chỉ quan sát, khó triển khai công nghiệp |
+| **Robot mode** | API với BMS, giữ cửa lâu, ưu tiên cabin trống — phổ biến nhất |
+| **Thang chuyên dụng** | Chỉ robot dùng, điều khiển hoàn toàn qua API |
+
+## 2.5 Chức năng thang tại từng giai đoạn mission
+
+### Giai đoạn 1: Trước cửa thang (tầng nguồn)
+
+**Thang:** Nhận call, di chuyển cabin, mở cửa, báo ready.
+
+**Robot:** Đi đến `elevator_wait_point`, chờ `door_open` + `current_floor == my_floor`.
+
+### Giai đoạn 2: Vào cabin
+
+**Thang:** `hold_door` trong khi robot vào.
+
+**Robot:** Tắt/hạ độ tin cậy SLAM, dùng odometry ngắn, gửi `request_ride(dest_floor)` khi vào xong.
+
+### Giai đoạn 3: Trong cabin (đang chạy)
+
+**Thang:** Báo `moving`, `current_floor`, `at_destination` + `door_open`.
+
+**Robot:** Đứng yên, **không cố SLAM**, chờ tín hiệu thang.
+
+### Giai đoạn 4: Ra cabin (tầng đích)
+
+**Thang:** Giữ cửa mở cho đến khi robot báo `exited`.
+
+**Robot:** Ra đến relocalization zone, load map tầng đích, relocalize, sau đó `release_door`.
+
+## 2.6 Thang như "cạnh" trong đồ thị điều hướng
+
+```
+Floor 1: [Room] --- [Elev1_Wait] ====ELEVATOR==== [Elev1_Exit]
+ |
+Floor 3: [Room] --- [Elev1_Wait] ====ELEVATOR==== [Elev1_Exit]
+ |
+Floor 5: [Room] --- [Elev1_Wait] ====ELEVATOR==== [Elev1_Exit]
+```
+
+**Thuộc tính của cạnh thang:**
+
+- **Cost** = thời gian chờ + thời gian chạy + độ tin cậy
+- **Constraint** = chỉ đi được khi `elevator.available == true`
+- **Precondition** = robot tại `wait_point`, thang `ready`
+- **Postcondition** = robot tại `exit_point` tầng đích, đã relocalize
+
+## 2.7 Chức năng phụ quan trọng
+
+- **Timeout & retry** — Gọi thang quá lâu → đổi thang hoặc hủy mission
+- **Interlock an toàn** — Robot trong cabin, thang fault, lệch inside_pose
+- **Multi-robot coordination** — Queue, gán elevator_id, tránh tranh cabin
+- **Ghi log / audit** — Debug khi SLAM lệch sau khi ra thang
+
+## 2.8 Phân chia trách nhiệm
+
+| Việc | Ai làm |
+|---|---|
+| Biết vị trí trên hành lang từng tầng | Robot (SLAM/AMCL) |
+| Lập đường trong tầng | Robot (local planner) |
+| Vào/ra cabin không va chạm | Robot (local nav + odometry) |
+| Relocalize sau khi ra | Robot |
+| Chọn thang nào trong tòa nhà | Fleet / mission manager |
+| Mở cửa, chạy tầng, báo trạng thái | Thang (qua BMS/API) |
+
+## 2.9 Ví dụ luồng sự kiện đầy đủ
+
+```
+1. Mission: F2 → F5 qua Elevator B
+2. Robot nav đến Elev_B_wait (F2) [SLAM hoạt động]
+3. Robot → Elev: call(2)
+4. Elev → Robot: moving_to_2
+5. Elev → Robot: arrived, door_open
+6. Robot → Elev: hold_door
+7. Robot nav vào cabin (2m) [odom chính, SLAM phụ]
+8. Robot → Elev: entered, ride_to(5)
+9. Robot → Elev: release_door (cho đóng)
+10. Elev: moving 2→5
+11. Elev → Robot: floor=3,4... (optional)
+12. Elev → Robot: arrived_5, door_open
+13. Robot → Elev: hold_door
+14. Robot nav ra + relocalize (F5) [SLAM bật lại]
+15. Robot → Elev: exited, release_door
+16. Robot nav đến đích trên map F5
+```
+
+---
+
+# Tóm tắt
+
+## Ba trụ cột của hệ thống
+
+1. **Perception / Localization** — biết vị trí trên từng tầng
+2. **Building integration** — điều khiển và đọc trạng thái thang máy
+3. **Mission orchestration** — quy trình vào/ra thang và chuyển map
+
+## Sáu chức năng cốt lõi của thang máy
+
+1. **Transport** — chuyển tầng vật lý
+2. **Gateway** — nối hai không gian/map SLAM tách biệt
+3. **Access** — kiểm soát cửa và thời điểm vào/ra
+4. **Signaling** — cung cấp trạng thái mà SLAM không suy ra được
+5. **Resource** — tài nguyên dùng chung cần đặt chỗ và xếp hàng
+6. **Safety envelope** — vùng vận hành có rủi ro cao, cần interlock
+
+## Kết luận
+
+> **AMR multi-floor không phải một SLAM map khổng lồ 3D**, mà là **nhiều map 2D + đồ thị kết nối qua thang máy + state machine điều phối thang + relocalization khi đổi tầng**.
+
+Thang máy là **cầu nối có điều kiện** giữa các map — robot SLAM điều hướng trong từng tầng, còn thang đảm nhiệm **chuyển tầng + đồng bộ trạng thái + kiểm soát cửa**; localization được **tạm ngưng trong cabin** và **khôi phục sau khi ra**.
diff --git a/docs/AMR_SLAM_Thang_May.pdf b/docs/AMR_SLAM_Thang_May.pdf
new file mode 100644
index 0000000..6d27e50
Binary files /dev/null and b/docs/AMR_SLAM_Thang_May.pdf differ
diff --git a/docs/Reference_guide.md b/docs/Reference_guide.md
index 8d9d2b7..2ca765e 100644
--- a/docs/Reference_guide.md
+++ b/docs/Reference_guide.md
@@ -229,8 +229,415 @@ List, upload, nghe, play trên robot, CRUD (không xóa system sound). API: `/ap
### 4.5 Setup — Transitions — ✅
+> **Tham chiếu MiR** (xem [SOURCES_MiR.md](SOURCES_MiR.md)):
+> - MiR robot Reference Guide **rev 1.9** (03/2019, SW 2.6.0) — §4.1.4.3 *Switch Map*, §4.4 *Transitions*
+> - MiR robot Reference Guide **v2.2** (02/2021) — bản sửa cách diễn đạt, tr. 43 & 90–92
+> - **MiRFleet** Reference Guide SW 2.5.0 (01/2019) — §4.3 *Elevators*
+> - **MiR Fleet Enterprise** v1.2 (01/2025) — tr. 107–108 *Transitions*, tr. 325–329 *Create transitions / Ramps / Elevators*
+
List, filter, pager, CRUD dialog (site, from/to map, start/goal position, mission). API: `/api/transitions`. File: `www/transitions.js`.
+#### Nguyên lý hoạt động
+
+**Mục đích.** Transition xử lý việc robot chuyển từ map này sang map khác trong **cùng một site** (ví dụ hai nhà xưởng kề nhau, mỗi nơi một map). Khi đã cấu hình, mission chỉ cần `move_to_position` tới đích trên map khác; hệ thống tự chèn chuỗi chuyển map — người lập mission không phải gọi `switch_map` thủ công ở mọi chỗ.
+
+**Thành phần của một transition**
+
+| Trường | Ý nghĩa |
+|--------|---------|
+| Site | Cả hai map phải thuộc cùng site |
+| From map / To map | Map nguồn → map đích (chiều A→B và B→A là hai bản ghi / hai mission riêng) |
+| Start position | Position kiểu robot trên **map nguồn**, tại điểm hai map chồng lên nhau |
+| Goal position | Position kiểu robot trên **map đích**, **cùng vị trí vật lý** với Start (tên khác nhau, tọa độ thế giới trùng) |
+| Mission | Mission chuyển map (thường chứa action `switch_map` và các bước liên quan cửa/PLC nếu cần) |
+
+#### Phân tích chức năng lệnh Switch map (MiR §4.1 / dùng trong §4.4.1)
+
+**Định nghĩa (MiR).** `Switch map` đổi bản đồ navigation đang dùng trong một mission khi site có nhiều map. Hai map phải có vùng overlap để robot định vị lại trên map mới. Action này là **nền tảng** của Transition: khi Transition đã cấu hình, hệ thống tự chèn switch khi mission chỉ lệnh đi sang position thuộc map khác.
+
+> **Đính chính thuật ngữ (v1.9 → v2.2).** Bản 1.9 viết móc nối nhầm sang *Goal position*; bản **v2.2 sửa lại** cho đúng: điểm overlap phải khớp với **Entry position** của chính action Switch map.
+>
+> - v1.9: *"…physically overlaps the **Goal position** you select here"*
+> - v2.2: *"The Switch map action must be preceded by a Move action to the position in the current map that physically overlaps the **Entry position in the other map** that the robot is switching to."*
+>
+> → Khi đối chiếu tài liệu cũ, hiểu **Goal (transition) ≡ Entry (action Switch map)** — cùng một điểm vật lý.
+
+**Việc Switch map làm (ý nghĩa chức năng)**
+
+| Khía cạnh | Nội dung |
+|-----------|----------|
+| Input ngữ cảnh | Robot đang đứng tại điểm chồng trên map **from** (đã `move` tới Start trước đó) |
+| Thay đổi trạng thái | Đặt map **to** làm map active (bản đồ planner / localization) |
+| Định vị lại sau đổi map | Dùng Entry/Goal position trên map **to** (cùng chỗ vật lý với Start trên map from) để khớp pose trên map mới |
+| Đầu ra | Các lệnh `move_to_position` tiếp theo resolve theo map mới |
+
+Không di chuyển cơ học xuyên tường/tầng: robot **đứng yên (hoặc gần điểm chồng)**, đổi “hệ tọa độ map”, rồi tiếp tục mission trên map đích.
+
+**Mission Transition cần *mấy* Switch map? — MiR đổi quan điểm theo thời gian**
+
+Đây là điểm **hai thế hệ tài liệu MiR nói khác nhau**, cần biết để không cấu hình thừa:
+
+| Nguồn | Yêu cầu | Nguyên văn |
+|-------|---------|------------|
+| Reference Guide 1.9 (2019) | **Hai** Switch map | *"must include two Switch map actions: the first… the 'from' map and the defined start position, and the second… the 'to' map and the defined goal position"* |
+| Reference Guide v2.2 (2021) | **Hai** Switch map | giữ nguyên diễn đạt trên |
+| **Fleet Enterprise v1.2 (2025)** | **Một** Switch map | *"A transition mission that contains **a** Switch map action"* (tr. 107) · *"A transition mission must consist of **a** Switch map action that specifies which map the robot must switch to and which position it starts from"* (tr. 328) |
+
+Mô hình **hai** action (đời cũ):
+
+| # | Switch map | Ý nghĩa |
+|---|------------|---------|
+| 1 | From map + Start position | Định vị lại / khẳng định đang ở điểm chồng trên map nguồn trước khi đổi |
+| 2 | To map + Entry (= Goal) position | Đổi sang map đích và định vị lại tại cùng điểm vật lý |
+
+→ **Kết luận cho robot_app:** thiết kế hiện tại (**một** `switch_map` → map đích, Start/Goal do bản ghi Transition + runtime lo) **trùng khớp với hướng dẫn mới nhất của MiR (2025)**, không phải sai lệch so với chuẩn. Action đầu trong mô hình cũ chỉ mang tính "khẳng định vị trí" — runtime robot_app đã đảm bảo bằng bước *đi tới Start* trước khi chạy mission TR.
+
+**Trường trên MiR (action editor)**
+
+| Trường | Nội dung |
+|--------|----------|
+| **Entry Position** | Position trên map **to** — điểm robot "bắt đầu" sau khi chuyển map (tương đương Goal của Transition) |
+| Biến | v2.2 cho phép chọn **XYZ icon** để đặt Entry Position thành **biến mission** (robot_app: chưa có) |
+
+**Trên robot_app hiện tại**
+
+| | MiR | robot_app |
+|--|-----|-----------|
+| Tham số UI | Entry position (+ ngữ cảnh from/to trong transition mission) | Chủ yếu `map_id` (`switch_map`) |
+| Runtime | Đổi map nav + localize tại entry | `setActiveMap` / ghi `robot_runtime.active_map_id` |
+| Vai trò với Transition | Nằm trong mission TR; auto-transition chèn quanh Start/Goal | Mission TR chạy `switch_map`; sau đó queue vẫn `setActiveMap(to)` và move Goal |
+| Số `switch_map` trong mission TR | 1.9 / v2.2: **2** · Fleet Enterprise 2025: **1** | **1** `switch_map` → map đích; Start/Goal do Transition + runtime lo → **khớp chuẩn 2025** |
+
+Triển khai: `MissionQueue` xử lý `type == "switch_map"` → `setActiveMapOnRobotRuntimeDoc`; auto-transition thêm một lần set map active sau mission TR.
+
+**Khi nào dùng Switch map**
+
+1. **Trong mission Transition** (khuyến nghị) — cùng I/O thang / cửa nếu cần.
+2. **Trong mission vận hành thủ công** — ít dùng nếu đã có Transition (trùng / dễ lệch so với auto).
+3. **Không thay** `move_to_position`: Switch map không đi từ A đến B; chỉ đổi map tại điểm chồng.
+
+**Điều kiện thành công**
+
+- Đã tới vùng overlap (Start) trước khi đổi map.
+- Start/Goal cùng điểm vật lý, tên khác, map khác, cùng site.
+- Map đích tồn tại; sau switch, localization khớp Goal/Entry.
+
+**Điều kiện vật lý.** Start và Goal phải nằm đúng một điểm chồng (overlap) giữa hai map — robot dừng ngắn ở đó để định vị lại trên map mới trước khi tiếp tục đi.
+
+**Luồng runtime (robot_app)** — khi mission đang chạy gặp `move_to_position` / `adjust_localization` mà position thuộc map khác map đang active:
+
+```
+Map A (đang active) Map B (đích)
+───────────────── ─────────────
+ … đi bình thường
+ Position đích ∈ Map B?
+ │
+ ▼
+ Tìm transition A → B (TransitionStore.findBetween)
+ │ không có → lỗi "No transition configured"
+ ▼
+ 1. Di chuyển tới Start (trên Map A)
+ 2. Chạy Transition mission (không cho auto-transition lồng nhau)
+ 3. switch_map → đặt Map B active
+ 4. Định vị / di chuyển tới Goal (trên Map B)
+ 5. Tiếp tục move_to_position tới đích gốc trên Map B
+```
+
+Triển khai: `MissionQueue::runAutoTransitionIfNeeded` trong `src/mission/mission_queue.cpp`. Transition mission chạy với `allow_auto_transition = false` để tránh vòng lặp.
+
+**Tóm tắt hành vi người dùng.** Sau khi tạo transition trong UI (MiR §4.4.1): thiết kế mission như môi trường một map; khi queue chạy tới lệnh đi sang map khác, robot tự dừng tại điểm chồng, chạy mission chuyển map, đổi map, rồi tiếp tục — chỉ “nhìn thấy” khoảng dừng ngắn khi chuyển.
+
+#### Trường hợp đặc biệt: khu chuyển map là thang máy
+
+Hai tầng không “chồng sàn” như hai nhà xưởng. Điểm giao là **khu thang máy**. Với **thứ tự runtime hiện tại** (`đi tới Start` → chạy mission TR → `switch_map` → đi Goal), không nên đặt Start ngay trong cabin nếu cửa còn đóng — robot sẽ cố đi vào cabin **trước** khi gọi thang.
+
+##### MiR chính thức nói gì về thang máy
+
+Hai sản phẩm Fleet của MiR xử lý thang máy **ngược nhau** — đây là căn cứ quan trọng cho lựa chọn thiết kế của robot_app:
+
+| Sản phẩm | Hỗ trợ thang máy | Cách làm |
+|----------|------------------|----------|
+| **MiRFleet SW 2.5.0** (2019) | ✅ **Có sẵn** (§4.3 *Elevators*) | Fleet tự "takes over", đưa robot vào/ra cabin đúng tầng và **tự đổi map nội bộ** |
+| **MiR Fleet Enterprise v1.2** (2025) | ❌ **Đã bỏ** | *"MiR Fleet Enterprise **does not support elevators**. Use MiR Fleet Integration API to define your own elevator control."* |
+
+Hướng dẫn của bản 2025 khi cần thang máy (tr. 311):
+
+> *"For elevators, you must make a **custom elevator control system**. You can create **transition positions inside the elevator** on the map for each floor and **set up transitions for each floor shift**."*
+
+→ **Cách robot_app đang làm — mission TR tự viết logic I/O gọi thang + `switch_map`, transition riêng cho mỗi chiều/tầng — chính là cách MiR khuyến nghị ở bản mới nhất.** Không phải giải pháp chắp vá.
+
+**Mô hình elevator của MiRFleet 2.5.0** (tham khảo để đặt tên/bố trí position — xác nhận bố cục bên dưới là đúng chuẩn):
+
+| Trường MiRFleet | Ý nghĩa | Tương ứng robot_app |
+|-----------------|---------|---------------------|
+| **Position in the elevator** | Position robot **bên trong cabin** | `Cabin_A` / `Cabin_B` |
+| **Position in front of the elevator** | Position **ngoài cửa**, nơi robot **chờ thang tới và cửa mở** | `Tr_Start_AB` / `Tr_Goal_AB` |
+| **Entry mission** / **Exit mission** | MiR tách **hai** mission: vào thang và ra thang | robot_app gộp trong **một** mission TR |
+| **Floor** | Số tầng — **bắt buộc là số** (tầng trệt = `0`, hầm = `-1`) | Quy ước đặt tên map |
+| **IP address** | IP hệ thống thang (do nhà tích hợp thang cung cấp) | Cấu hình I/O module |
+| **Turn in place** | Cho phép robot xoay trong cabin hay không | Nới collision trong cabin |
+| **Door** | 1 = xoay 180° ra cùng cửa vào · 2 = không xoay, ra cửa đối diện | Thiết kế Cabin/Goal theo hướng |
+
+Lưu ý MiRFleet: map mỗi tầng **phải chứa hai elevator position** (trong cabin + trước cửa) thì mới chuyển map được — trùng với bố trí 4 position của robot_app.
+
+**Bố trí position khuyến nghị (thang máy + robot_app)**
+
+| Position | Map | Vị trí | Vai trò |
+|----------|-----|--------|---------|
+| Pos_A | Map_A | Điểm làm việc | Đích/điểm xuất phát vận hành |
+| **Tr_Start_AB** | Map_A | **Trước cửa thang** (chờ) | Start của Transition — runtime đi tới đây trước |
+| Cabin_A | Map_A | **Trong cabin** | Dùng trong mission TR (vào thang) |
+| Cabin_B | Map_B | **Trong cabin** (cùng XY Cabin_A) | Định vị lại sau `switch_map` |
+| **Tr_Goal_AB** | Map_B | **Trước cửa thang** tầng B | Goal của Transition — ra thang / chờ cửa |
+| Pos_B | Map_B | Điểm làm việc | Đích vận hành |
+
+**Cách viết mission**
+
+1) Mission vận hành `Go_A_to_B` — chỉ việc “đi làm”, **không** viết cửa/cabin:
+
+| # | Action | Position |
+|---|--------|----------|
+| 1 | `move_to_position` | Pos_A *(tuỳ chọn)* |
+| 2 | `move_to_position` | **Pos_B** |
+
+Khi tới bước 2, runtime thấy Pos_B ∈ Map_B → tự chạy Transition A→B rồi mới tới Pos_B.
+
+2) Mission Transition `TR_MapA_to_MapB` — **toàn bộ** cửa → vào → đi tầng → ra:
+
+| # | Action | Nội dung |
+|---|--------|----------|
+| 1 | `set_digital_output` / PLC | Gọi thang / chọn tầng A (nếu cần) |
+| 2 | `wait_digital_input` | Chờ thang tới, **cửa mở** |
+| 3 | `move_to_position` | **Cabin_A** (vào thang) |
+| 4 | I/O | Đóng cửa, lệnh đi **tầng B** |
+| 5 | `wait_digital_input` | Chờ tới tầng B, cửa mở |
+| 6 | `switch_map` | **Map_B** |
+| 7 | `adjust_localization` hoặc `move_to_position` | **Cabin_B** (định vị lại trên map mới) |
+| 8 | `move_to_position` | Ra gần cửa / **Tr_Goal_AB** *(tuỳ chọn — runtime cũng đi Goal sau)* |
+
+3) Transition record: Start = `Tr_Start_AB`, Goal = `Tr_Goal_AB`, Mission = `TR_MapA_to_MapB`.
+
+**Chuỗi thực tế khi bấm Dashboard**
+
+```
+Pos_A
+ → (ops) move Pos_B kích hoạt Transition
+ → runtime: tới Tr_Start_AB (cửa tầng A)
+ → TR: gọi thang → vào Cabin_A → đi tầng → switch_map → Cabin_B → ra cửa
+ → runtime: tới Tr_Goal_AB (cửa tầng B)
+ → (ops) tiếp tục tới Pos_B
+```
+
+**Lưu ý**
+
+- Cabin_A / Cabin_B vẫn là điểm **định vị lại** an toàn trong cabin; Tr_Start/Goal đặt **ngoài cửa** cho khớp thứ tự “đi Start trước khi chạy TR”.
+- Chiều B→A: mission TR + transition riêng.
+- I/O module thang phải cấu hình trước (Setup → I/O modules).
+- Cabin hẹp: nới collision / speed zone trong cabin.
+
+**Lưu ý vận hành**
+
+- Cần **hai** transition (và thường hai mission) nếu muốn đi hai chiều A↔B.
+- Chưa có transition A→B mà mission yêu cầu position trên B → mission **fail**.
+- Transition được export/import theo site bundle cùng maps.
+- Quyền: resource `maps` (xem ma trận auth §2).
+- Qua thang: lỗi I/O / tín hiệu cửa không tới → mission dừng ở bước Wait; không tự retry tầng khác trừ khi viết Try/Catch (chưa đủ trên robot_app).
+
+**Nguyên tắc thiết kế map & transition** (MiR Fleet Enterprise 2025, tr. 325)
+
+| Nguyên tắc | Lý do |
+|------------|-------|
+| Cắt map tại nơi có **một lối vào duy nhất** | Robot buộc phải đi qua transition position để đổi map → cắt ở chỗ thắt cổ chai là tự nhiên nhất |
+| Được phép tạo **nhiều transition** giữa cùng cặp map | Nhưng mỗi cái tốn công cấu hình + bảo trì → chỉ thêm khi thật cần |
+| **Bắt buộc** transition cho **cả hai chiều** | Hai chiều có thể **cùng** một chỗ hoặc **khác** chỗ |
+| Transition hướng **theo chiều luồng giao thông** | Tránh robot đi ngược dòng tại điểm giao |
+| Muốn kiểm soát chỗ robot chuyển vùng → **chia nhỏ map** | Kết hợp map zone để điều tiết planner/traffic |
+
+**Ramp (dốc nối tầng).** MiR xếp ramp cùng nhóm với thang máy — *"Transitions are often also used when changing floors with ramps or elevators."* Nếu robot không tự plan qua dốc, MiR khuyên thêm **Access zone** phủ lên vạch đỏ phát hiện sàn ở chân dốc. robot_app: chưa có zone loại Access.
+
+#### Hướng dẫn cài đặt: gọi robot từ điểm A (map A) → điểm B (map B)
+
+Mục tiêu: operator bấm một nút trên Dashboard → robot đi từ **Pos_A** trên **Map_A** tới **Pos_B** trên **Map_B**. Transition A→B chạy tự động khi mission yêu cầu position sang map khác.
+
+##### Bước 1 — Thiết kế map
+
+1. **Setup → Maps**: tạo (hoặc chọn) **một Site** chứa cả Map_A và Map_B.
+2. Tạo **Map_A** và **Map_B**; upload ảnh / occupancy / YAML nếu có; vẽ floor, tường, forbidden…
+3. Trên **Map_A** tạo các robot position:
+ - **Pos_A** — điểm xuất phát (điểm A).
+ - **Tr_Start_AB** — điểm chồng / chờ chuyển map (sàn kề: vùng overlap; **thang máy: trước cửa thang**).
+ - *(Thang máy)* **Cabin_A** — trong cabin, dùng trong mission TR.
+4. Trên **Map_B** tạo:
+ - **Tr_Goal_AB** — điểm chồng tương ứng (thang máy: trước cửa tầng B).
+ - *(Thang máy)* **Cabin_B** — trong cabin, cùng XY với Cabin_A.
+ - **Pos_B** — điểm đích (điểm B).
+5. Lưu map. Đảm bảo map active ban đầu là Map_A khi robot đang đứng ở Pos_A (định vị / Adjust localization nếu cần).
+
+> **Cách tạo cặp Start/Goal cho *đúng cùng một điểm vật lý*** — quy trình MiR Fleet Enterprise 2025 (tr. 327). Đây là bước dễ sai nhất: gõ tay toạ độ hai map hầu như luôn lệch.
+>
+> | # | Thao tác |
+> |---|----------|
+> | 1 | Định vị robot chuẩn trên **Map_A** (Adjust localization) |
+> | 2 | **Lái robot tới đúng điểm overlap** giữa hai map |
+> | 3 | Xoay robot **hướng đúng chiều đi vào khu vực mới** |
+> | 4 | ⚠️ **Từ đây KHÔNG di chuyển robot nữa** cho tới hết bước 7 |
+> | 5 | Trên Map_A: tạo Robot position **từ vị trí hiện tại của robot** → `Tr_Start_AB` |
+> | 6 | **Kích hoạt Map_B**, định vị lại robot **mà không dời robot** |
+> | 7 | Trên Map_B: tạo Robot position **từ vị trí hiện tại** → `Tr_Goal_AB` |
+>
+> Đặt tên position thể hiện rõ nó thuộc transition nào. MiR: *"The transitions must point in the same direction as the traffic flow."*
+
+> Thang máy: logic gọi thang / vào–ra cabin viết trong mission TR (Bước 2), không viết trong mission vận hành.
+##### Bước 2 — Tạo mission chuyển map (dùng cho Transition)
+
+**Setup → Missions** → tạo mission riêng, ví dụ `TR_MapA_to_MapB` (không phải mission vận hành hàng ngày).
+
+Nội dung tối thiểu (sàn kề nhau):
+
+| # | Action | Tham số gợi ý |
+|---|--------|----------------|
+| 1 | `switch_map` | Map = Map_B |
+| 2 | (tuỳ chọn) `adjust_localization` / `move_to_position` | Tr_Goal_AB |
+
+Nội dung kiểu thang máy — xem bảng đầy đủ ở mục *Khu chuyển map là thang máy*; tóm tắt:
+
+`gọi thang → chờ cửa → move Cabin_A → đi tầng → chờ cửa → switch_map Map_B → Cabin_B → (ra cửa)`
+
+Lưu mission. Chiều ngược B→A cần mission + transition riêng nếu muốn đi hai chiều.
+
+##### Bước 3 — Tạo Transition
+
+**Setup → Transitions → Create transition:**
+
+| Trường | Giá trị |
+|--------|---------|
+| Site | Site chứa Map_A, Map_B |
+| From map | Map_A |
+| To map | Map_B |
+| Start position | Tr_Start_AB |
+| Goal position | Tr_Goal_AB |
+| Mission | `TR_MapA_to_MapB` |
+
+Lưu. Không có bản ghi này → mission vận hành sẽ lỗi *No transition configured* khi đi sang Map_B.
+
+##### Bước 4 — Tạo mission vận hành A → B
+
+**Setup → Missions** → tạo ví dụ `Go_A_to_B`:
+
+| # | Action | Tham số |
+|---|--------|---------|
+| 1 | `move_to_position` | Pos_A (tuỳ chọn — đảm bảo đứng đúng điểm A) |
+| 2 | `move_to_position` | **Pos_B** |
+
+Chỉ cần gọi Pos_B trên Map_B. Runtime tự:
+
+`… → tới Tr_Start_AB → chạy TR_MapA_to_MapB → switch map → Tr_Goal_AB → tới Pos_B`.
+
+Không nhúng toàn bộ logic chuyển map vào `Go_A_to_B` (trừ khi cố ý không dùng Transition).
+
+##### Bước 5 — Dashboard gọi robot
+
+1. **Dashboards** → tạo / mở dashboard (vd. *Operator*).
+2. Chế độ **Edit** → **Add widget**:
+ - `mission_button` — chọn mission `Go_A_to_B`, đặt nhãn nút (vd. «A → B»).
+ - Nên thêm `mission_queue`, `pause_continue`, (tuỳ chọn) `map` / `mission_action_log`.
+3. Gán **Permissions** user group được phép xem/dùng dashboard.
+4. Lưu → chuyển **Operate**.
+
+Operator bấm nút → `POST /api/mission_queue` → robot_app chạy queue. Có thể kiểm tra tại Setup → Missions (panel queue) hoặc Monitoring → Mission log.
+
+##### Sơ đồ tổng thể
+
+```
+[Map design] Pos_A, Tr_Start_AB trên Map_A
+ Tr_Goal_AB, Pos_B trên Map_B
+ │
+ ▼
+[Mission TR] TR_MapA_to_MapB (switch_map ± I/O thang)
+ │
+ ▼
+[Transition] Map_A → Map_B, Start/Goal, gắn mission TR
+ │
+ ▼
+[Mission ops] Go_A_to_B: move → Pos_A?, move → Pos_B
+ │
+ ▼
+[Dashboard] mission_button → queue → robot chạy A→B (auto transition)
+```
+
+##### Kiểm tra nhanh
+
+| Kiểm tra | Kỳ vọng |
+|----------|---------|
+| Bấm nút Dashboard | Entry xuất hiện trên mission queue |
+| Robot đang Map_A, đích Pos_B | Log: Auto transition Map_A → Map_B |
+| Thiếu Transition | Lỗi *No transition configured* |
+| Sai I/O thang | Dừng ở Wait for input trong mission TR |
+
+##### Logic vận hành (runtime)
+
+Thứ tự khi operator gọi robot đi **Pos_A (Map_A) → Pos_B (Map_B)**:
+
+```
+Operator bấm mission_button (Go_A_to_B)
+ │
+ ▼
+POST /api/mission_queue → entry status = pending
+ │
+ ▼
+MissionQueue worker (FIFO)
+ lấy entry pending đầu tiên → status = executing
+ runner.state = running
+ │
+ ▼
+Thực thi từng action của Go_A_to_B
+```
+
+**Action 1 — `move_to_position` Pos_A** (nếu có)
+
+1. Resolve Pos_A; so sánh `map_id` với map đang active.
+2. Cùng Map_A → đi thẳng tới Pos_A; cập nhật `last_position_id`.
+3. Khác map → kích hoạt auto-transition trước (xem dưới), rồi mới hoàn tất move.
+
+**Action 2 — `move_to_position` Pos_B** (điểm mấu chốt)
+
+1. Resolve Pos_B → thuộc **Map_B**; active đang là **Map_A** → khác map.
+2. Gọi `runAutoTransitionIfNeeded(Map_A, Map_B)`:
+ - Không tìm thấy transition A→B → **fail** (`No transition configured`).
+ - Có transition:
+ 1. Di chuyển tới **Start** (`Tr_Start_AB`) trên Map_A
+ 2. Chạy mission gắn transition (`TR_MapA_to_MapB`) với `allow_auto_transition=false` (không lồng transition)
+ — trong đó: I/O thang (nếu có), `switch_map`, …
+ 3. Runtime đặt map active = **Map_B** (sau mission TR)
+ 4. Di chuyển tới / định vị lại tại **Goal** (`Tr_Goal_AB`) trên Map_B
+3. Sau transition: hoàn tất `move_to_position` tới **Pos_B** trên Map_B.
+4. `last_position_id` = Pos_B.
+
+**Kết thúc mission**
+
+| Kết quả | Hành vi |
+|---------|---------|
+| Thành công | entry = finished / done; runner → idle (nếu hết queue); ghi Mission log (persisted) |
+| Cancel (topbar / pause_continue) | dừng giữa action; entry hủy |
+| Lỗi (thiếu transition, I/O, switch_map…) | runner.state = error; ghi error log |
+
+**Pause / Continue / Cancel**
+
+- Queue chỉ lấy entry `pending` khi không `paused`.
+- Pause: dừng nhận / tạm dừng runner; Continue: tiếp tục.
+- Cancel: hủy mission đang `executing`.
+
+**Song song nhiều lệnh**
+
+- Nhiều lần bấm nút → nhiều entry **pending** xếp hàng; chỉ **một** mission chạy tại một thời điểm (FIFO).
+
+**Topbar / Dashboard phản ánh**
+
+- Strip mission + state: từ `GET /api/robot/status` / runner.
+- Widget `mission_queue`: danh sách pending/executing.
+- Widget `mission_action_log`: vài dòng log action đang chạy.
+- Monitoring → Mission log: lịch sử sau khi chạy xong.
+
### 4.6 Setup — Users — ✅
List, filter, CRUD, PIN 4 số. API: `/api/users`. File: `www/users.js`.
diff --git a/docs/SOURCES_MiR.md b/docs/SOURCES_MiR.md
new file mode 100644
index 0000000..6bc7c2a
--- /dev/null
+++ b/docs/SOURCES_MiR.md
@@ -0,0 +1,31 @@
+# Nguồn tài liệu MiR (Mobile Industrial Robots)
+
+Tải ngày **2026-07-23**. Chủ đề nghiên cứu: **action Switch map / Transitions / điều hướng đa tầng**.
+
+## Tài liệu đã tải
+
+| File | Mô tả | Phiên bản / Ngày | Nguồn |
+|------|-------|------------------|-------|
+| `Reference guide.pdf` | MiR robot Reference Guide — tài liệu gốc, đầy đủ nhất về Switch map & Transitions (mục 4.1.4.3, 4.4) | rev 1.9 — 03/2019 (SW 2.6.0) | [cdn.kyklo.co](https://cdn.kyklo.co/assets/W1siZiIsIjIwMTkvMTAvMTYvMTgvNTgvNTYvMGNkOTJiZGQtZGYzMS00OTVmLThlMGEtMWUwODhiNzQ1ODgwL01pUiUyMC0lMjBNaVIlMjByb2JvdCUyMHJlZmVyZW5jZSUyMGd1aWRlLnBkZiJdXQ?sha=9b51843b3f3b3c7f) |
+| `mir_reference_guide_2.2_2021_en.pdf` | MiR robot Reference Guide bản mới hơn | v2.2 — 02/2021 | [supportportal.mobile-industrial-robots.com](https://supportportal.mobile-industrial-robots.com/support-files/manuals/html/en/ref_guide_robots_2.2/content/_resources/pdf/mir%C2%A0robot%20reference%20guide%202.2_en.pdf) |
+| `mir_fleet_enterprise_1.2_2025_en.pdf` | MiR Fleet Enterprise — điều hướng đa tầng, thang máy, REST API | v1.2 — 01/2025 | [jk.de](https://jk.de/media/a2/50/ce/1738939330/mir_fleet_enterprise_documentation_1.2_en.pdf?ts=1738939330) |
+| `mir_fleet_reference_guide_sw2.5.0_2019_en.pdf` | MiRFleet Reference Guide — mục Elevators, quản lý nhiều robot/nhiều map | SW 2.5.0 — 01/2019 | [iptech1.com](https://iptech1.com/wp-content/uploads/2019/01/mirfleet_reference_guide_sw250_rev10.pdf) |
+| `mir250_user_guide_11_en.pdf` | MiR250 User Guide (đã có sẵn từ trước) | v1.1 | — |
+| `mir_software_official_page.html` | Trang chính thức MiR Software (xác nhận tính năng "switch maps fast") | — | [mobile-industrial-robots.com](https://mobile-industrial-robots.com/solutions/mir-applications/mir-software) |
+| `neff_mir_positions_and_missions.html` | Hướng dẫn thực hành: Positions & Missions với MiR AMR | — | [neffautomation.com](https://neffautomation.com/blog/mir-amrs-positions-and-missions) |
+
+## Mật độ từ khóa (số lần xuất hiện)
+
+| File | `switch map` | `elevator` | `transition` |
+|------|--------------|------------|--------------|
+| `mir_reference_guide_2.2_2021_en.pdf` | 10 | 3 | 25 |
+| `mir_fleet_enterprise_1.2_2025_en.pdf` | 2 | 11 | 70 |
+| `mir_fleet_reference_guide_sw2.5.0_2019_en.pdf` | 9 | 28 | 21 |
+
+→ Tra cứu **Switch map action**: ưu tiên `Reference guide.pdf` (1.9) và `mir_reference_guide_2.2_2021_en.pdf`.
+→ Tra cứu **thang máy / đa tầng**: ưu tiên `mir_fleet_reference_guide_sw2.5.0_2019_en.pdf` và `mir_fleet_enterprise_1.2_2025_en.pdf`.
+
+## Ghi chú
+
+- Bản v1.9 trên `cdn.kyklo.co` trả về **HTTP 403** khi tải bằng curl, nhưng file `Reference guide.pdf` sẵn có trong thư mục đã đúng là bản này (đã xác minh trang bìa: *Revision 1.9 / 2019/03*).
+- `manuals.plus` (Getting started, MiR200 REST API) chặn truy cập tự động (**403**) — cần mở thủ công bằng trình duyệt nếu cần.
diff --git a/docs/Slamtec_Robot_Comparison.xlsx b/docs/Slamtec_Robot_Comparison.xlsx
new file mode 100644
index 0000000..3b4e478
Binary files /dev/null and b/docs/Slamtec_Robot_Comparison.xlsx differ
diff --git a/docs/mir_fleet_enterprise_1.2_2025_en.pdf b/docs/mir_fleet_enterprise_1.2_2025_en.pdf
new file mode 100644
index 0000000..71feb81
Binary files /dev/null and b/docs/mir_fleet_enterprise_1.2_2025_en.pdf differ
diff --git a/docs/mir_fleet_reference_guide_sw2.5.0_2019_en.pdf b/docs/mir_fleet_reference_guide_sw2.5.0_2019_en.pdf
new file mode 100644
index 0000000..a5740ea
Binary files /dev/null and b/docs/mir_fleet_reference_guide_sw2.5.0_2019_en.pdf differ
diff --git a/docs/mir_reference_guide_2.2_2021_en.pdf b/docs/mir_reference_guide_2.2_2021_en.pdf
new file mode 100644
index 0000000..da5b46b
Binary files /dev/null and b/docs/mir_reference_guide_2.2_2021_en.pdf differ
diff --git a/docs/mir_software_official_page.html b/docs/mir_software_official_page.html
new file mode 100644
index 0000000..82af91b
--- /dev/null
+++ b/docs/mir_software_official_page.html
@@ -0,0 +1,3 @@
+
MiR Software | MiR
MiR Software
If you see MiR AMRs as just a means of moving goods from A to B, chances are you haven’t yet discovered the full capability of MiR’s software. Depending on your need for integration, scalability, and operational control, MiR offers a flexible software suite. On-robot software and our fleet management software provide centralized fleet management for efficient daily operations.
MiR Fleet Enterprise delivers enterprise-ready, cybersecure fleet control designed for advanced scalability and complex integration. Additionally, MiR Insights provides data to help you optimize AMR utilization.
The MiR software is next generation software that helps you get maximum throughput of your AMRs. It enables your MiR robots to operate efficiently - individually and in large fleets.
The navigation of AMRs is better than ever with MiR Software: the robots can reroute smoothly, switch maps fast, and interact easily thanks to an enhanced user-interface and planner that optimize driving patterns and avoid bottlenecks.
When you want to optimize the usage of your MiR robots, MiR Insights help you visualize and analyze your fleet.
If you’re looking to automate tasks with MiR AMRs, setting up positions and missions is essential. In this guide, we'll walk you through setting up positions, creating missions, and even building a custom dashboard for your MiR robot with MiR's third software update.
You’ll need to set positions for your robot to navigate. In this demo, we’re working with a cart that needs to be picked up and dropped off at specific locations. To begin, create your first position. For example, you can label it Position A, where the robot will find the cart.
+
+
When setting a position, you’ll notice the arrow indicates the entry point. If it's incorrect, simply rotate the position to ensure the robot approaches from the correct direction. Once that’s set, save the position and move on to creating another one, which we've called Position B.
+
+
+
+
2. Building Missions to Automate Tasks
+
Now that you have your positions set up, it’s time to create missions. Missions tell the MiR robot what actions to take at each position. In this case, we need to instruct the robot to pick up the cart at Position A and drop it off at Position B.
+
+
We selected our pre-built mission template, "Pick Up MiR 250 Shelf," for our demo. Ensure the correct footprint and cart are selected for Position A, then save and update the mission.
+
+
Next, create a second mission for dropping off the cart at Position B. This time, start with a Move command followed by a Place Shelf command. Make sure you specify Position B as the drop-off location.
+
+
For added flexibility, create two more missions: one to Pick Up at B and another to Drop at A. With these four missions, your robot can seamlessly transport the cart between positions.
+
+
+
+
3. Testing Your Missions
+
Once your missions are built, it’s time to test them out. Go back to your map and verify that your cart is aligned with the correct position. Then, queue the mission to Pick Up at A. Switch your MiR robot to automatic mode and hit the play button.
+
+
As the robot approaches the cart, you’ll notice it might turn slightly left or right. This is normal—the robot is using its scanners to adjust its approach, ensuring it can pick up the cart even if it’s slightly out of position. This flexibility allows the robot to handle minor variations in cart placement.
+
+
After successfully picking up the cart, queue the mission to Drop at B. You should see the robot navigate to Position B and drop off the cart smoothly. If the cart isn’t perfectly still when the robot backs away, don’t worry—the robot uses its sensors to avoid collisions.
+
+
+
+
4. Creating a Custom Dashboard
+
To make operations even easier, you can create a custom dashboard to control your MiR robot with just a few clicks. Navigate to the Dashboard section of the MiR software and click Create. Start by adding a map and a few mission buttons.
+
+
For this setup, we’ll add buttons for Pick Up at A, Pick Up at B, Drop at A, andDrop at B. Drag and adjust the buttons to your preferred layout. Finally, add a mission queue to monitor the robot's progress.
+
Once you’ve customized the dashboard to your liking, hit Save. Now you have a user-friendly interface to run your missions with just a few clicks.
+
+
+
+
5. Testing the Dashboard
+
With your dashboard set up, it’s time to put it to use. For this demo, the cart is sitting at Position B, so start with the Pick Up at B command. You can also direct the robot to move further up the aisle before dropping it off at Position A.
+
+
By running these commands through the dashboard, you’ll see how easily the MiR robot completes its tasks with minimal human intervention.
+
+
Setting up positions, missions, and a custom dashboard in MiR software version 3 is straightforward and efficient. With just a few steps, you can fully automate tasks like cart transportation, making your operations smoother and more reliable.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/ĐỀ XUẤT MỞ DỰ ÁN NGHIÊN CỨU BASE ROBOT DỊCH VỤ.docx b/docs/ĐỀ XUẤT MỞ DỰ ÁN NGHIÊN CỨU BASE ROBOT DỊCH VỤ.docx
new file mode 100644
index 0000000..16e3968
Binary files /dev/null and b/docs/ĐỀ XUẤT MỞ DỰ ÁN NGHIÊN CỨU BASE ROBOT DỊCH VỤ.docx differ