7.5 KiB
7.5 KiB
robot::WallTimer Usage Guide
Overview
robot::WallTimer is a class similar to ros::WallTimer that allows you to call a callback function at a specified rate using wall-clock time. It creates a separate thread that periodically invokes your callback function.
Key Difference from Timer:
TimerusesTimeandDuration(can be affected by simulated time)WallTimerusesWallTimeandWallDuration(always uses real wall-clock time)
This makes WallTimer ideal for:
- Performance monitoring and profiling
- Real-time deadlines and timeouts
- Hardware interfaces requiring precise timing
- Benchmarking and measurement
- Any task that needs to run at real-world intervals
Basic Usage
Simple WallTimer Example
#include <robot/wall_timer.h>
#include <iostream>
void myCallback(const robot::WallTimerEvent& event)
{
std::cout << "WallTimer fired! Current wall 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 (wall-clock time)
robot::WallTimer timer(
robot::WallDuration(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::WallDuration(5.0).sleep();
// Stop the timer
timer.stop();
return 0;
}
Using with Class Methods
#include <robot/wall_timer.h>
class PerformanceMonitor
{
public:
void startMonitoring()
{
// Create timer with member function callback
timer_ = std::make_unique<robot::WallTimer>(
robot::WallDuration(0.5), // 2 Hz (every 0.5 seconds)
[this](const robot::WallTimerEvent& event) {
this->monitorCallback(event);
},
false, // Repeating
true // Auto-start
);
}
void monitorCallback(const robot::WallTimerEvent& event)
{
// Do periodic performance monitoring here
// This always uses real wall-clock time, not simulated time
std::cout << "Performance check at real time: "
<< event.current_real.toSec() << std::endl;
}
void stopMonitoring()
{
if (timer_)
{
timer_->stop();
}
}
private:
std::unique_ptr<robot::WallTimer> timer_;
};
One-Shot WallTimer
#include <robot/wall_timer.h>
void delayedAction(const robot::WallTimerEvent& event)
{
std::cout << "Delayed action executed after 5 seconds (real time)" << std::endl;
}
int main()
{
// Create a one-shot timer that fires once after 5 seconds (wall-clock)
robot::WallTimer timer(
robot::WallDuration(5.0), // Wait 5 seconds
delayedAction, // Callback
true, // One-shot
true // Auto-start
);
// Wait for timer to fire
robot::WallDuration(6.0).sleep();
return 0;
}
WallTimerEvent Structure
The WallTimerEvent structure passed to your callback contains:
current_real: The actual wall-clock time when the callback was calledcurrent_expected: The expected wall-clock time when the callback should have been calledlast_real: The actual wall-clock time of the previous callbacklast_expected: The expected wall-clock time of the previous callbacklast_duration: The wall-clock duration between the last two callbacks
All times are in wall-clock time (real time), not simulated time.
API Reference
Constructor
WallTimer(const WallDuration& period,
const Callback& callback,
bool oneshot = false,
bool autostart = true);
period: Time between callbacks (wall-clock duration)callback: Function to call (signature:void(const WallTimerEvent&))oneshot: If true, timer fires only onceautostart: If true, timer starts automatically
Methods
void start(): Start the timer. Does nothing if already started.void stop(): Stop the timer. Once this returns, no more callbacks will be called.void setPeriod(const WallDuration& period, bool reset = true): Set the timer period. Ifresetis true, timer ignores elapsed time and next callback occurs at now()+period.bool hasStarted(): Check if timer is runningbool isValid(): Check if timer has a valid callbackbool hasPending(): Check if timer has any pending events to callbool isOneShot(): Check if timer is one-shotvoid setOneShot(bool oneshot): Set one-shot modeWallDuration getPeriod(): Get the timer period
Operators
operator void*(): Conversion to bool (for checking validity)operator==(const WallTimer&): Equality comparisonoperator!=(const WallTimer&): Inequality comparisonoperator<(const WallTimer&): Less-than comparison (for ordering in containers)
Comparison: Timer vs WallTimer
| Feature | Timer |
WallTimer |
|---|---|---|
| Time Type | Time / Duration |
WallTime / WallDuration |
| Simulated Time | Can be affected | Never affected |
| Use Case | ROS message timestamps, simulation | Performance, real-time, hardware |
| Initialization | Requires Time::init() |
No initialization needed |
| Exception | Can throw if time not initialized | Never throws |
Example: Performance Profiling
#include <robot/wall_timer.h>
class Profiler
{
public:
void startProfiling()
{
profile_timer_ = std::make_unique<robot::WallTimer>(
robot::WallDuration(1.0), // Profile every 1 second
[this](const robot::WallTimerEvent& event) {
this->profileCallback(event);
},
false, // Repeating
true // Auto-start
);
}
void profileCallback(const robot::WallTimerEvent& event)
{
// Measure actual wall-clock time between callbacks
double actual_interval = event.last_duration.toSec();
double expected_interval = 1.0;
if (actual_interval > expected_interval * 1.1) // 10% tolerance
{
std::cout << "WARNING: Timer drift detected! "
<< "Expected: " << expected_interval
<< "s, Actual: " << actual_interval << "s" << std::endl;
}
}
private:
std::unique_ptr<robot::WallTimer> profile_timer_;
};
Example: Dynamic Period Adjustment
#include <robot/wall_timer.h>
robot::WallTimer timer(robot::WallDuration(1.0), myCallback);
// Later, change the period
timer.setPeriod(robot::WallDuration(0.5), true); // Reset to 0.5s, reset timer
// Or change without reset
timer.setPeriod(robot::WallDuration(2.0), false); // Change to 2s, don't reset
Best Practices
- Use WallTimer for real-time operations: When you need precise wall-clock timing
- Use Timer for ROS messages: When working with ROS messages that use simulated time
- Always stop timers: Make sure to call
stop()before destroying the timer - Handle exceptions in callbacks: Exceptions in callbacks are caught to prevent timer thread crashes
- Check validity: Use
isValid()oroperator void*()to check if timer has a callback
Thread Safety
WallTimer is thread-safe:
- Multiple threads can safely call
start(),stop(),setPeriod(), etc. - The callback is executed in a separate thread
- All internal state is protected by mutexes
References
- ROS WallTimer Documentation
TIMER_USAGE.md- Guide forrobot::Timer(uses simulated time)WALLTIME_USAGE.md- Guide forWallTimeandWallDuration