This commit is contained in:
Duong Vu
2026-07-22 10:42:09 +07:00
parent 4bb8ef9a2b
commit e1cce6e0ea
65 changed files with 3803 additions and 0 deletions

133
README.md
View File

@@ -1,2 +1,135 @@
# odomety
Thư viện C++ ước lượng odometry cho robot **differential drive** (2 bánh chủ động).
Từ vận tốc góc bánh xe, **encoder ticks**, hoặc lệnh `v`/`ω`, thư viện tích phân pose 2D `(x, y, θ)` và vận tốc `(v, ω)` theo thời gian.
## Tính năng
- Cập nhật từ vận tốc góc bánh trái/phải `[rad/s]`
- Cập nhật từ cumulative encoder ticks (`Encoder_Measurement`-style)
- Cập nhật trực tiếp từ lệnh tuyến tính/góc `[m/s]`, `[rad/s]`
- Tích phân exact (và RungeKutta bậc 2 khi gần đi thẳng)
- Làm mượt vận tốc bằng rolling mean (Boost Accumulators)
- Demo và unit test kèm theo
## Yêu cầu
- CMake ≥ 3.14
- C++17
- Boost (header: Accumulators, Function)
## Cấu trúc
```
odomety/
├── include/odometry/odom_differential.h
├── src/odom_differential.cpp
├── src/main.cpp # demo
├── test/odom_differential_test.cpp
└── CMakeLists.txt
```
## Build
```bash
cd odomety
cmake -S . -B build
cmake --build build
```
Chạy demo:
```bash
./build/odomety_demo
```
Chạy test:
```bash
cd build && ctest --output-on-failure
# hoặc
./build/odomety_test
```
## Cài đặt (tùy chọn)
```bash
sudo cmake --install build --prefix /path/to/install
```
Trong project khác:
```cmake
find_package(odomety REQUIRED)
target_link_libraries(your_target PRIVATE odomety::odom_differential)
```
## Cách dùng
### Từ vận tốc bánh
```cpp
#include <odometry/odom_differential.h>
differential::Odometry odom(/*velocity_rolling_window_size=*/10);
odom.setWheelParams(
/*wheel_separation=*/0.5, // [m]
/*left_wheel_radius=*/0.09, // [m]
/*right_wheel_radius=*/0.09 // [m]
);
odom.init(/*time_sec=*/t0);
odom.updateWheel(left_omega, right_omega, t); // [rad/s]
```
### Từ encoder ticks (khuyến nghị khi có đếm xung)
```cpp
odom.setWheelParams(0.5, 0.09, 0.09);
odom.setEncoderParams(/*ticks_per_revolution=*/4096); // phía bánh, sau gearbox
odom.init(t0);
// Cumulative tick counts (unwrap overflow về int64 monotonic trước khi gọi)
odom.updateTicks(left_ticks, right_ticks, t); // lần đầu chỉ seed, trả về false
double x = odom.getX();
double y = odom.getY();
double yaw = odom.getHeading();
double v = odom.getLinear();
double w = odom.getAngular();
```
Công thức nội bộ mỗi bước:
- `Δs_L/R = 2π · r_L/R · Δn_L/R / N_L/R`
- `Δs = (Δs_L + Δs_R) / 2`
- `Δθ = (Δs_R Δs_L) / b`
### Từ lệnh vận tốc (open-loop)
```cpp
odom.updateOdom(linear_mps, angular_rps, t);
```
## API chính
| Hàm | Mô tả |
|---|---|
| `init(time)` | Reset pose/vận tốc/tick seed và gắn timestamp |
| `setWheelParams(sep, r_l, r_r)` | Khoảng cách bánh và bán kính |
| `setEncoderParams(N)` / `setEncoderParams(N_l, N_r)` | CPR phía bánh |
| `updateWheel(ω_l, ω_r, time)` | Cập nhật từ vận tốc góc bánh |
| `updateTicks(n_l, n_r, time)` | Cập nhật từ cumulative encoder ticks |
| `updateOdom(v, ω, time)` | Cập nhật từ lệnh vận tốc |
| `getX/Y/Heading/Linear/Angular()` | Đọc trạng thái hiện tại |
## Ghi chú
- `updateWheel` / `updateTicks` trả về `false` nếu `dt < 0.0001` s.
- `updateTicks`: lần gọi đầu sau `init` chỉ lưu tick trước đó (seed), không tích phân.
- `updateTicks` trả về `false` nếu chưa gọi `setEncoderParams` (CPR ≤ 0).
- Tick phải là đếm **phía bánh** (sau gearbox). Overflow counter phần cứng cần unwrap về `int64` monotonic.
- Đơn vị thời gian là giây (epoch hoặc monotonic, miễn nhất quán).
- Pose mặc định sau `init`: `(0, 0, 0)`.