robot_time/TIMER_EVENT_EXPLANATION.md
2026-01-10 10:17:17 +07:00

213 lines
5.9 KiB
Markdown

# TimerEvent - Giải thích và Cách sử dụng
## TimerEvent là gì?
`TimerEvent` là một structure chứa thông tin về timing của timer callback. Nó được truyền vào mỗi lần callback được gọi, giúp bạn biết:
- Timer có chạy đúng thời gian không?
- Timer có bị delay không?
- Khoảng thời gian thực tế giữa các lần callback
## Các thành phần của TimerEvent
```cpp
struct TimerEvent
{
Time current_real; // Thời gian thực tế khi callback được gọi
Time current_expected; // Thời gian dự kiến khi callback nên được gọi
Time last_real; // Thời gian thực tế của lần callback trước
Time last_expected; // Thời gian dự kiến của lần callback trước
Duration last_duration; // Khoảng thời gian thực tế giữa 2 lần callback
};
```
## Tại sao cần TimerEvent?
### 1. **Phát hiện Timer Drift (Lệch thời gian)**
Timer có thể bị lệch do:
- Hệ thống bận
- Thread scheduling
- Callback mất nhiều thời gian
```cpp
void myCallback(const robot::TimerEvent& event)
{
// Tính độ lệch thời gian
robot::Duration drift = event.current_real - event.current_expected;
if (drift.toSec() > 0.1) // Lệch hơn 100ms
{
std::cout << "Warning: Timer is " << drift.toSec() << " seconds late!" << std::endl;
}
}
```
### 2. **Đo thời gian thực tế giữa các callback**
Không phải lúc nào timer cũng chạy đúng period. Bạn có thể đo thời gian thực tế:
```cpp
void myCallback(const robot::TimerEvent& event)
{
// Thời gian thực tế giữa 2 lần callback
double actual_period = event.last_duration.toSec();
double expected_period = 1.0; // Period bạn set
if (actual_period > expected_period * 1.1) // Lệch hơn 10%
{
std::cout << "Timer is running slow! Expected: " << expected_period
<< ", Actual: " << actual_period << std::endl;
}
}
```
### 3. **Tính toán thời gian xử lý**
Bạn có thể biết callback mất bao lâu:
```cpp
robot::Time callback_start;
void myCallback(const robot::TimerEvent& event)
{
callback_start = robot::Time::now();
// Do some work...
doSomeWork();
robot::Duration processing_time = robot::Time::now() - callback_start;
robot::Duration time_until_next = event.current_expected + period - robot::Time::now();
if (processing_time > time_until_next)
{
std::cout << "Warning: Callback takes longer than period!" << std::endl;
}
}
```
### 4. **Điều chỉnh hành vi dựa trên timing**
Ví dụ: Nếu timer bị delay, có thể bỏ qua một số công việc:
```cpp
void myCallback(const robot::TimerEvent& event)
{
robot::Duration drift = event.current_real - event.current_expected;
if (drift.toSec() > 0.5) // Delay quá nhiều
{
// Bỏ qua công việc không quan trọng
return;
}
// Thực hiện công việc bình thường
doImportantWork();
}
```
### 5. **Logging và Debugging**
TimerEvent rất hữu ích để debug:
```cpp
void myCallback(const robot::TimerEvent& event)
{
static int count = 0;
count++;
if (count % 100 == 0) // Log mỗi 100 lần
{
robot::Duration drift = event.current_real - event.current_expected;
double avg_period = event.last_duration.toSec();
std::cout << "Timer Stats:" << std::endl;
std::cout << " Callback #" << count << std::endl;
std::cout << " Current drift: " << drift.toSec() << " seconds" << std::endl;
std::cout << " Average period: " << avg_period << " seconds" << std::endl;
std::cout << " Expected period: " << period.toSec() << " seconds" << std::endl;
}
}
```
## Ví dụ thực tế trong move_base
Trong code của bạn, `wakePlanner` có thể sử dụng TimerEvent để:
```cpp
void move_base::MoveBase::wakePlanner(const robot::TimerEvent& event)
{
// Kiểm tra xem timer có chạy đúng không
robot::Duration drift = event.current_real - event.current_expected;
if (drift.toSec() > 0.05) // Lệch hơn 50ms
{
robot::log_warning("Planner timer is running late by %.3f seconds", drift.toSec());
}
// Thời gian thực tế giữa 2 lần wake
double actual_period = event.last_duration.toSec();
double expected_period = 1.0 / planner_frequency_;
if (actual_period > expected_period * 1.2) // Lệch hơn 20%
{
robot::log_warning("Planner frequency is lower than expected. "
"Expected: %.2f Hz, Actual: %.2f Hz",
planner_frequency_, 1.0 / actual_period);
}
// Wake up planner thread
planner_cond_.notify_one();
}
```
## Khi nào nên sử dụng TimerEvent?
### Nên dùng khi:
- ✅ Cần monitor timer performance
- ✅ Cần phát hiện timer drift
- ✅ Cần điều chỉnh hành vi dựa trên timing
- ✅ Debug timing issues
- ✅ Tính toán thời gian xử lý
### Không cần dùng khi:
- ❌ Callback đơn giản, không quan tâm timing
- ❌ Chỉ cần biết timer đã fire
- ❌ Không cần thông tin về drift
## Ví dụ đơn giản
```cpp
// Callback đơn giản - không dùng TimerEvent
void simpleCallback(const robot::TimerEvent& event)
{
// Không cần dùng event, chỉ cần biết timer đã fire
doSomething();
}
// Callback phức tạp - sử dụng TimerEvent
void advancedCallback(const robot::TimerEvent& event)
{
// Sử dụng event để monitor
double drift = (event.current_real - event.current_expected).toSec();
if (std::abs(drift) > 0.01) // Lệch hơn 10ms
{
adjustBehavior(drift);
}
doSomething();
}
```
## Tóm tắt
`TimerEvent` cung cấp thông tin timing chi tiết giúp bạn:
1. **Monitor** timer performance
2. **Phát hiện** timing issues
3. **Điều chỉnh** hành vi dựa trên timing
4. **Debug** timing problems
5. **Tối ưu** performance
Trong hầu hết trường hợp đơn giản, bạn có thể bỏ qua TimerEvent. Nhưng khi cần monitor hoặc debug timing, nó rất hữu ích!