# robot::Timer Usage Guide ## Overview `robot::Timer` is a class similar to `ros::Timer` that allows you to call a callback function at a specified rate. It creates a separate thread that periodically invokes your callback function. ## Basic Usage ### Simple Timer Example ```cpp #include #include void myCallback(const robot::TimerEvent& event) { std::cout << "Timer fired! Current time: " << event.current_real.toSec() << std::endl; std::cout << "Time since last callback: " << event.last_duration.toSec() << " seconds" << std::endl; } int main() { // Create a timer that fires every 1 second robot::Timer timer( robot::Duration(1.0), // Period: 1 second myCallback, // Callback function false, // Not one-shot (repeats) true // Auto-start ); // Timer is now running... // Do other work here // Sleep for 5 seconds to see timer fire multiple times robot::Duration(5.0).sleep(); // Stop the timer timer.stop(); return 0; } ``` ### Using with Class Methods ```cpp #include class MyClass { public: void startTimer() { // Create timer with member function callback timer_ = std::make_unique( robot::Duration(0.5), // 2 Hz [this](const robot::TimerEvent& event) { this->timerCallback(event); }, false, // Repeating true // Auto-start ); } void timerCallback(const robot::TimerEvent& event) { // Do periodic work here std::cout << "Periodic task executed" << std::endl; } void stopTimer() { if (timer_) { timer_->stop(); } } private: std::unique_ptr timer_; }; ``` ### One-Shot Timer ```cpp #include void delayedAction(const robot::TimerEvent& event) { std::cout << "Delayed action executed after 5 seconds" << std::endl; } int main() { // Create a one-shot timer that fires once after 5 seconds robot::Timer timer( robot::Duration(5.0), // Wait 5 seconds delayedAction, // Callback true, // One-shot true // Auto-start ); // Wait for timer to fire robot::Duration(6.0).sleep(); return 0; } ``` ## TimerEvent Structure The `TimerEvent` structure passed to your callback contains: - `current_real`: The actual time when the callback was called - `current_expected`: The expected time when the callback should have been called - `last_real`: The actual time of the previous callback - `last_expected`: The expected time of the previous callback - `last_duration`: The duration between the last two callbacks ## API Reference ### Constructor ```cpp Timer(const Duration& period, const Callback& callback, bool oneshot = false, bool autostart = true); ``` - `period`: Time between callbacks - `callback`: Function to call (signature: `void(const TimerEvent&)`) - `oneshot`: If true, timer fires only once - `autostart`: If true, timer starts automatically ### Methods - `void start()`: Start the timer - `void stop()`: Stop the timer - `bool hasStarted()`: Check if timer is running - `bool isOneShot()`: Check if timer is one-shot - `void setOneShot(bool oneshot)`: Set one-shot mode - `Duration getPeriod()`: Get the timer period - `void setPeriod(const Duration& period)`: Set the timer period ## Example: Using in move_base Here's how you could use `robot::Timer` in the `planThread` function: ```cpp #include void move_base::MoveBase::planThread() { boost::unique_lock lock(planner_mutex_); while (true) { // Wait until we should run the planner while (!runPlanner_) { planner_cond_.wait(lock); } lock.unlock(); // Do planning work robot_geometry_msgs::PoseStamped temp_goal = planner_goal_; planner_plan_->clear(); bool gotPlan = makePlan(temp_goal, *planner_plan_); // ... handle plan result ... // If planner_frequency > 0, use timer to wake up later if (planner_frequency_ > 0) { robot::Duration sleep_time = robot::Duration(1.0 / planner_frequency_); // Create one-shot timer to wake up planner robot::Timer wake_timer( sleep_time, [this](const robot::TimerEvent&) { boost::unique_lock lock(planner_mutex_); planner_cond_.notify_one(); }, true, // One-shot true // Auto-start ); // Wait for timer or condition variable lock.lock(); planner_cond_.wait(lock); } else { lock.lock(); } } } ``` ## Thread Safety - `Timer` is thread-safe and can be started/stopped from any thread - The callback function is executed in a separate thread - Be careful when accessing shared data from the callback - use proper synchronization ## Notes - The timer uses `robot::Time` which respects simulation time if enabled - Timer accuracy depends on system scheduling and may drift slightly - For very high frequency timers (>100 Hz), consider using `robot::Rate` in a loop instead - The timer thread will automatically clean up when the `Timer` object is destroyed