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

5.2 KiB

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

#include <robot/timer.h>
#include <iostream>

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

#include <robot/timer.h>

class MyClass
{
public:
  void startTimer()
  {
    // Create timer with member function callback
    timer_ = std::make_unique<robot::Timer>(
      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<robot::Timer> timer_;
};

One-Shot Timer

#include <robot/timer.h>

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

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:

#include <robot/timer.h>

void move_base::MoveBase::planThread()
{
  boost::unique_lock<boost::recursive_mutex> 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<boost::recursive_mutex> 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