Lidarlib

Thư viện C++17 cho lidar OLEI (UDP) và SICK (TCP/UDP). Build bằng CMake ra shared lib, hỗ trợ find_package(lidarlib). Mọi driver dùng chung một interface lidarlib::Lidar và một hàm khởi tạo duy nhất lidarlib::make_lidar().

  • Tự nhận diện họ giao thức OLEI (Family A/B/C) theo từng gói tin
  • Tự dò model (MODEL_AUTO) với Family B/C
  • Chạy nhiều lidar song song (mỗi instance độc lập, an toàn đa luồng)
  • Output chuẩn ROS sensor_msgs/LaserScan (radian, mét)
  • Không có UI — tự viết giao diện trên API này

Build

cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j"$(nproc)"

Sinh ra build/liblidarlib.so (chỉ phụ thuộc pthread) và các binary demo (example, test_dual, sick_example, nanoscan_example, lidar_app).

Tùy chọn: -DLIDARLIB_BUILD_EXAMPLES=OFF (tắt demo), -DBUILD_SHARED_LIBS=OFF (static lib).

Cài đặt và dùng từ project khác:

cmake --install build --prefix "$HOME/.local"   # hoặc sudo với /usr/local
find_package(lidarlib REQUIRED)
target_link_libraries(my_app PRIVATE lidarlib::lidarlib)

Quick start

#include "lidarlib/lidarlib.hpp"   // toàn bộ API trong 1 include

lidarlib::LidarConfig c{"front", "192.168.1.10", 2368, "AUTO", false, "OLEI"};
std::unique_ptr<lidarlib::Lidar> lidar = lidarlib::make_lidar(c);
lidar->open();

lidarlib::ScanResult r;
lidar->recv_scan(r, 1000);
// r.scan : LaserScan — format sensor_msgs/LaserScan của ROS, chung mọi lidar
// r.info : ExtraInfo — thông tin thêm tuỳ family/model
printf("%zu diem, model=%s\n", r.scan.ranges.size(), r.info.detected_model.c_str());

Có thể khởi tạo driver trực tiếp thay vì qua make_lidar():

lidarlib::Driver      olei(lidarlib::MODEL_AUTO, "192.168.100.100", 2368);
lidarlib::SickDriver  tim (lidarlib::MODEL_SICK_TIM571, "192.168.0.1", 2111);
lidarlib::NanoScanDriver nano(lidarlib::MODEL_SICK_NANOSCAN3, "0.0.0.0", 6060);

Ngoài recv_scan() blocking còn có callback: set_scan_callback() + spin_once() trong vòng lặp riêng.

Cấu hình (config.json)

lidar_app là app mẫu headless: đọc config.json, mở từng lidar bằng make_lidar(), một thread mỗi con.

./build/lidar_app [my_config.json]
{
  "lidars": [
    {"name":"front", "ip":"192.168.100.100", "port":2368, "brand":"OLEI", "model":"AUTO", "inverted":false},
    {"name":"rear",  "ip":"192.168.100.100", "port":2369, "brand":"OLEI", "model":"AUTO", "inverted":true},
    {"name":"sick1", "ip":"192.168.0.1",     "port":2111, "brand":"SICK", "model":"SICK-TIM571"},
    {"name":"nano1", "ip":"0.0.0.0",         "port":6060, "brand":"SICK", "model":"SICK-nanoScan3"}
  ]
}
Trường Ý nghĩa
brand "OLEI" (mặc định) hoặc "SICK"
model Tên trong bảng model bên dưới; tên lạ → mặc định của hãng (AUTO / SICK-TIM571). Với SICK, "SICK-nanoScan3" → driver UDP, còn lại → driver TCP
inverted Chỉ OLEI: true nếu lidar lắp úp ngược, driver tự đảo góc về hệ quy chiếu xe
angle_min_deg / angle_max_deg Tuỳ chọn: remap tuyến tính góc output sang cửa sổ này (độ). Không cắt điểm nào, chỉ ghi lại angle_min/max/increment. Bỏ trống (±360) = tắt

Đọc/ghi bằng lidarlib::load_config(path) / lidarlib::save_config(path, cfg).

Model

OLEI (brand = "OLEI", UDP, port mặc định 2368)

Constant FOV (°) Range (m) Ghi chú
MODEL_VB -135…135 0.05…30 2D 270°, Family A
MODEL_VF -180…180 0.05…30 2D 360°, Family A
MODEL_LR1F -180…180 0.05…50 Family A; 0° thô của máy chỉ về đuôi (offset +180°)
MODEL_LR1FMI -180…180 0.05…30 Family B, ~2400 điểm/vòng; 0° thô chỉ về đuôi (offset +180°)
MODEL_LR1BS5 -180…180 0.05…30 Family B
MODEL_LR16F -135…135 0.05…30 3D 16-line
MODEL_GS15 -180…180 0.05…30 Family C/V3 — chưa verify phần cứng
MODEL_AUTO -180…180 0.05…30 Không biết trước model; tự dò với Family B (chuỗi tên) và C (magic). Family A không mang tên model nên giữ FOV rộng

Driver nhận diện họ giao thức theo Frame ID mỗi gói: Family A 0xFAF0 (header 20B, 3B/điểm, CRC32) · Family B 0xFEF0 (header 40B kèm tên model ASCII, 8B/điểm) · Family C/V3 0xFEAC (header 48B, 2/4B/điểm — port từ driver C#, chưa verify).

Tên model thật đọc từ packet xem qua detected_model() hoặc result.info.detected_model.

SICK (brand = "SICK")

Constant FOV (°) Range (m) Transport
MODEL_SICK_TIM5XX -135…135 0.05…10 TCP/SOPAS (CoLa-A), port 2111
MODEL_SICK_TIM571 -135…135 0.05…25 TCP/SOPAS, port 2111
MODEL_SICK_TIM7XX -135…135 0.05…25 TCP/SOPAS, port 2111
MODEL_SICK_NANOSCAN3 -137.5…137.5 0.05…40 UDP safety-data, port 6060

TiM (SickDriver)open() tự gửi sEN LMDscandata 1 để bắt đầu stream. Hệ góc trên dây đặt 90° = trước mặt nên preset có angle_offset_deg = -90, output ra -135…135° với 0° = phía trước. Đã verify trên TiM781S thật (811 điểm/scan, increment 0.333°, DIST1/RSSI1 đúng layout). Chưa verify: encoder, kênh 8-bit, thông số TiM5xx/571.

nanoScan3 (NanoScanDriver) — UDP receiver thụ động: chỉ bind cổng và parse datagram; đích UDP phải cấu hình sẵn trong SICK Safety Designer (driver không bắt tay CoLa2). Layout port từ sick_safetyscanners (Apache-2.0). Chưa verify phần cứng thật — mới test bằng gói tổng hợp qua loopback.

Output

ScanResult { LaserScan scan; ExtraInfo info; } mỗi vòng quét:

  • LaserScan — cùng field/đơn vị với ROS: angle_min/max/increment (rad, đã unwrap liên tục, không giới hạn ±π), ranges[] (m), intensities[] (0-255), timestamp_ms (đồng hồ thiết bị, 0 nếu family không có). range_min/max lấy từ ModelConfig (đặt sẵn, không đo mỗi scan); time_increment/scan_time luôn 0.
  • ExtraInfo — field tuỳ family: detected_model, error_status (Family A), distance_scale_mm (A/B), và các trường raw của Family C (chưa verify). Field thiết bị không có giữ std::nullopt.

Cấu trúc source

File Vai trò
include/lidarlib/lidar.hpp Data model, interface Lidar, driver OLEI, các MODEL_* OLEI
include/lidarlib/sick_lidar.hpp SickDriver, NanoScanDriver, các MODEL_SICK_*
include/lidarlib/config.hpp LidarConfig, load/save JSON, make_lidar()
src/olei_lidar.cpp Parse Family A/B/C, CRC, gom scan
src/sick_lidar.cpp Parse CoLa-A (TiM) + safety-data UDP (nanoScan3)
src/lidar_config.cpp Bảng model/brand, config JSON, factory
examples/ Demo: 1 lidar, 2 lidar song song, SICK TiM, nanoScan3, app khung

Ghi chú

  • Nếu port UDP đã bị app khác giữ (không bật SO_REUSEPORT), open() sẽ thất bại. Kiểm tra: ss -lunp | grep 2368.
  • inverted đã verify bằng sniff sống: false góc tăng dần, true góc giảm dần cùng bước.
Description
No description provided
Readme 556 KiB