Cập nhật tài liệu
This commit is contained in:
@@ -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`.
|
||||
|
||||
Reference in New Issue
Block a user