# 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!