add timer
This commit is contained in:
212
TIMER_EVENT_EXPLANATION.md
Normal file
212
TIMER_EVENT_EXPLANATION.md
Normal file
@@ -0,0 +1,212 @@
|
||||
# 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!
|
||||
|
||||
Reference in New Issue
Block a user