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