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

218 lines
5.2 KiB
Markdown

# 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 <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
```cpp
#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
```cpp
#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
```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 <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