10 KiB
Nghiên cứu: Dữ liệu chẩn đoán (diagnosis) của lidar OLEI & SICK
Tài liệu này tổng hợp những gì các gói dữ liệu OLEI mang theo về tình trạng
thiết bị (self-diagnostics), ngoài dữ liệu điểm quét. Kết quả nghiên cứu này
là cơ sở cho API lidarlib::Diagnostics / Lidar::get_diagnostics()
(header include/lidarlib/diagnostics.hpp).
Điểm quan trọng: lidar OLEI không có kênh/query chẩn đoán riêng — driver chỉ nhận UDP thụ động, thiết bị không nhận lệnh hỏi trạng thái. Toàn bộ thông tin chẩn đoán được nhúng trong header của chính gói dữ liệu quét, nên "lấy data diagnosis" = decode header của stream đang chạy, không tốn thêm băng thông hay round-trip nào.
1. Family A (Frame ID 0xFAF0 — VB, VF, LR-1F)
Header 20 byte, thông tin chẩn đoán nằm ở các offset sau:
| Offset | Kích thước | Trường | Ý nghĩa |
|---|---|---|---|
[4] |
u8 | distance_scale |
mm/count — gián tiếp cho biết chế độ đo |
[5] |
u8 | error_status |
Byte lỗi thiết bị, xem bảng bit bên dưới |
[10-11] |
u16 LE | rotation_raw |
Tốc độ quay motor (raw, đơn vị chưa xác minh — nghi là RPM hoặc Hz×100) |
[12-15] |
u32 LE | timestamp |
Đồng hồ thiết bị (ms) — dùng phát hiện thiết bị treo/reset |
Bit map của error_status (byte [5])
| Bit | Mask | Tên | Ý nghĩa khi = 1 |
|---|---|---|---|
| 0 | 0x01 |
Monitor | Khối giám sát/motor bất thường (motor không đạt tốc độ, mất đồng bộ encoder) |
| 1 | 0x02 |
Voltage | Điện áp nguồn ngoài dải cho phép |
| 2 | 0x04 |
Temperature | Nhiệt độ bên trong bất thường (quá nóng/quá lạnh) |
| 3-7 | 0xF8 |
Reserved | Chưa định nghĩa trong tài liệu OLEI; driver vẫn coi ≠0 là fault và log dạng reserved(0xXX) |
Ghi chú thực nghiệm:
- Trên thiết bị chạy bình thường byte này luôn
0x00; chưa tái tạo được fault thật trên phần cứng (chưa thử hạ áp/che gương), nên ý nghĩa bit lấy theo tài liệu giao thức OLEI, chưa verify từng bit bằng lỗi thật. error_statuslặp lại trong mỗi packet (~22°/packet), nhưng driver chỉ chốt giá trị theo vòng quét (lầnflush_scan()gần nhất) — đủ nhanh (10-20 Hz) và nhất quán vớiScanResult.
2. Family B (Frame ID 0xFEF0 — LR-1BS5, LR-1FMI)
Header 40 byte mang tên model ASCII tại [7-16] và distance_scale tại
[6], nhưng không có byte lỗi, không có timestamp. Đã dò toàn bộ 40 byte
header trên stream thật của LR-1FMI: các byte còn lại là hằng số/counter,
không thấy trường nào đổi giá trị khi thiết bị hoạt động — kết luận Family B
không phát dữ liệu chẩn đoán trên wire.
Chẩn đoán khả dụng duy nhất với Family B là gián tiếp:
- Mất gói /
ErrorCode::Timeouttừrecv_scan()→ thiết bị ngắt kết nối hoặc treo. - Số điểm mỗi vòng tụt bất thường (LR-1FMI chuẩn ~2400 điểm/vòng) → nghi bẩn kính / lỗi quang học.
get_diagnostics() với Family B trả về valid = true sau scan đầu tiên nhưng
error_status = 0 và mọi trường optional là nullopt — nghĩa là "không có
thông tin", không đồng nghĩa "thiết bị khỏe".
3. Family C / Protocol V3 (Magic 0xFEAC — GS1-5)
Header 48 byte, giàu thông tin trạng thái nhất (GS1-5 là dòng có field
an toàn kiểu safety-scanner). Các trường chẩn đoán (port từ driver C#
OleiGS15Driver.cs, chưa verify trên phần cứng thật):
| Offset | Kích thước | Trường | Ý nghĩa (theo driver C#) |
|---|---|---|---|
[24-25] |
u16 LE | scan_frequency_raw |
Tần số quét raw (nghi Hz×100) |
[28-29] |
u16 LE | input_status |
Trạng thái các chân input số |
[30-31] |
u16 LE | output_status |
Trạng thái các chân output số (OSSD?) |
[32-35] |
u32 LE | field_status |
Trạng thái các vùng field an toàn (bit nào = vùng nào chưa rõ) |
[44-47] |
u32 LE | status_flags |
Cờ trạng thái tổng — bit map chưa có tài liệu |
Vì bit map chưa xác minh, driver truyền nguyên giá trị raw qua
Diagnostics (các trường std::optional) thay vì decode sai. Khi có tài
liệu V3 chính thức hoặc thiết bị GS1-5 để thử, bổ sung decode tại
decode_diagnostics() trong src/olei_lidar.cpp.
4. SICK TiM (TCP/CoLa-A — telegram LMDscandata)
Khác OLEI, TiM có hai đường lấy chẩn đoán:
-
Nhúng trong stream (driver dùng đường này): telegram
sSN LMDscandatamang cặp Device Status ngay sau SerialNumber. Theo SICK Telegram Listing (8014631):Cặp giá trị Ý nghĩa 0 0OK 0 1Error — thiết bị lỗi, dữ liệu không tin được 0 2Pollution warning — kính bắt đầu bẩn, vẫn đo được 0 4Pollution error — kính bẩn nặng, phải lau Driver ghép cặp này vào
info.sick_device_status((word0<<8)|word1) và decode quasick_error()/pollution_warning()/pollution_error(). Ngoài ra telegram còn mang input/output số (input_status/output_status) và tần số quét (scan_frequency_raw, đơn vị 1/100 Hz). Chưa verify trên TiM781S thật với kính bẩn — cần che/bôi bẩn kính để xác nhận giá trị 2/4. -
Query chủ động qua SOPAS (chưa implement):
sRN SCdevicestate(0=busy, 1=ready, 2=error),sRN LCMstate(mức nhiễm bẩn),sRN DItype/sRN ODoprh(giờ vận hành). Cần cơ chế request/response xen giữa stream — xem mục Hướng mở rộng.
5. SICK nanoScan3 (UDP safety-data — block General System State)
Packet UDP của nanoScan3 gồm nhiều block, header trỏ tới từng block bằng cặp
offset/size. Block General System State (offset tại header [32], size
[34]) là block trạng thái an toàn; byte 0 của block (layout theo
sick_safetyscanners, chưa verify phần cứng):
| Bit | Mask | Ý nghĩa khi = 1 |
|---|---|---|
| 0 | 0x01 |
Run mode active (đang chạy bình thường) |
| 1 | 0x02 |
Standby mode |
| 2 | 0x04 |
Contamination warning — kính bẩn nhẹ |
| 3 | 0x08 |
Contamination error — kính bẩn nặng, vùng an toàn không tin được |
| 4 | 0x10 |
Reference contour status |
| 5 | 0x20 |
Manipulation — nghi bị che/can thiệp cố ý |
Driver đọc byte này vào info.nano_general_state, decode qua
contamination_warning() / contamination_error() / manipulation().
Lưu ý: block này chỉ có mặt nếu được tick chọn trong cấu hình data output
của Safety Designer — thiếu block thì trường giữ nullopt.
6. Chẩn đoán tầng transport (mọi driver)
Ngoài dữ liệu trên wire, bản thân driver cung cấp lớp chẩn đoán kết nối:
| Tín hiệu | API | Ý nghĩa |
|---|---|---|
| Không mở được socket | open() → ErrorCode |
Lỗi cấu hình host (port bận, IP sai...) |
Không có gói trong timeout_ms |
recv_scan() = false + last_error() == Timeout |
Đứt cáp, thiết bị mất nguồn, sai port |
| Lỗi recv giữa chừng | last_error() == DeviceDisconnected |
Socket lỗi cứng |
timestamp_ms nhảy lùi |
so sánh giữa 2 scan (Family A) | Thiết bị vừa reset/reboot |
Chiến lược giám sát khuyến nghị cho app: coi cảm biến healthy khi và chỉ
khi recv_scan() thành công đều đặn và get_diagnostics().has_fault() == false.
7. API
#include "lidarlib/lidarlib.hpp"
lidarlib::ScanResult r;
if (lidar->recv_scan(r, 1000)) {
lidarlib::Diagnostics d = lidar->get_diagnostics();
if (!d.valid) {
// chưa có scan nào được decode (hoặc driver không hỗ trợ — SICK)
} else if (d.has_fault()) {
// Family A: đọc từng bit
if (d.voltage_fault()) /* điện áp bất thường */;
if (d.temperature_fault()) /* nhiệt độ bất thường */;
if (d.monitor_fault()) /* motor/giám sát bất thường */;
printf("lidar fault: %s\n", lidarlib::to_string(d).c_str());
}
// SICK: cảnh báo kính bẩn — chưa phải fault nhưng nên lên lịch lau
if (d.has_warning()) {
d.pollution_warning(); // TiM
d.contamination_warning(); // nanoScan3
}
if (d.manipulation()) /* nanoScan3: nghi bị che/can thiệp */;
// Family C raw (nullopt nếu không phải GS1-5)
if (d.status_flags) printf("status_flags=0x%08X\n", *d.status_flags);
}
Lidar::get_diagnostics()— snapshot từ vòng quét decode gần nhất; gọi từ cùng thread đang bơmrecv_scan()/spin_once()(driver không khóa nội bộ).decode_diagnostics(const ExtraInfo&)— hàm free, decode trực tiếp từScanResult::infonếu app muốn gắn chẩn đoán với đúng scan cụ thể.to_string(Diagnostics)— chuỗi log 1 dòng:no data/ok/WARN: pollution/FAULT: voltage temperature.has_fault()gộp mọi nguồn lỗi (OLEI byte lỗi, TiM device/pollution error, nano contamination error/manipulation);has_warning()gộp các mức cảnh báo kính bẩn.
8. Hướng mở rộng
- SICK SOPAS query chủ động:
sRN SCdevicestate(0=busy, 1=ready, 2=error),sRN LCMstate(mức nhiễm bẩn chi tiết) — cần cơ chế request/response xen giữa streamLMDscandata. - Family A bit 3-7: cần bảng tra từ OLEI hoặc thử nghiệm gây lỗi có chủ đích (hạ áp nguồn, chặn tản nhiệt) để xác minh.
- GS1-5: cần thiết bị thật để xác minh toàn bộ Family C.
- TiM pollution 2/4: cần thử che/bôi bẩn kính TiM781S thật để xác nhận.