467 lines
12 KiB
Markdown
467 lines
12 KiB
Markdown
# WallTime - Hướng dẫn sử dụng
|
|
|
|
## Tổng quan
|
|
|
|
`WallTime` là class đại diện cho **thời gian thực (wall-clock time)** trong thư viện `robot_time`. Khác với `Time`, `WallTime` luôn sử dụng thời gian thực từ hệ thống và **không bị ảnh hưởng bởi simulated time**.
|
|
|
|
## Đặc điểm chính
|
|
|
|
### 1. Luôn sử dụng thời gian thực
|
|
- `WallTime` luôn lấy thời gian từ system clock
|
|
- Không phụ thuộc vào simulated time
|
|
- Không cần khởi tạo (`Time::init()`)
|
|
- Không bao giờ throw exception
|
|
|
|
### 2. Không cần khởi tạo
|
|
```cpp
|
|
// Time - CẦN khởi tạo
|
|
robot::Time::init(); // Phải gọi trước
|
|
robot::Time t = robot::Time::now(); // Có thể throw exception
|
|
|
|
// WallTime - KHÔNG cần khởi tạo
|
|
robot::WallTime t = robot::WallTime::now(); // Luôn hoạt động
|
|
```
|
|
|
|
### 3. Không bị ảnh hưởng bởi simulated time
|
|
```cpp
|
|
// Trong simulation với /use_sim_time = true
|
|
robot::Time t1 = robot::Time::now(); // Trả về simulated time
|
|
robot::WallTime t2 = robot::WallTime::now(); // Vẫn trả về thời gian thực
|
|
```
|
|
|
|
## API Reference
|
|
|
|
### Constructors
|
|
|
|
```cpp
|
|
// Default constructor - khởi tạo với giá trị 0
|
|
robot::WallTime t1;
|
|
|
|
// Constructor với giây và nanosecond
|
|
robot::WallTime t2(1234567890, 123456789);
|
|
|
|
// Constructor từ số thực (giây)
|
|
robot::WallTime t3(1234567890.123456789);
|
|
```
|
|
|
|
### Static Methods
|
|
|
|
#### `static WallTime now()`
|
|
Trả về thời gian hiện tại (wall-clock time).
|
|
|
|
```cpp
|
|
robot::WallTime current_time = robot::WallTime::now();
|
|
```
|
|
|
|
**Đặc điểm:**
|
|
- Luôn trả về thời gian thực
|
|
- Không cần khởi tạo trước
|
|
- Không throw exception
|
|
- Thread-safe
|
|
|
|
#### `static bool sleepUntil(const WallTime& end)`
|
|
Ngủ cho đến khi đạt đến thời điểm `end`.
|
|
|
|
```cpp
|
|
robot::WallTime end_time = robot::WallTime::now() + robot::WallDuration(5.0);
|
|
bool success = robot::WallTime::sleepUntil(end_time);
|
|
```
|
|
|
|
**Return value:**
|
|
- `true`: Đã ngủ đến thời điểm mong muốn
|
|
- `false`: Bị gián đoạn hoặc có lỗi
|
|
|
|
#### `static bool isSystemTime()`
|
|
Luôn trả về `true` vì `WallTime` luôn sử dụng system time.
|
|
|
|
```cpp
|
|
bool is_system = robot::WallTime::isSystemTime(); // Luôn là true
|
|
```
|
|
|
|
### Methods kế thừa từ `TimeBase`
|
|
|
|
#### Chuyển đổi đơn vị
|
|
|
|
```cpp
|
|
robot::WallTime t(1234567890, 123456789);
|
|
|
|
// Chuyển sang giây (double)
|
|
double seconds = t.toSec(); // 1234567890.123456789
|
|
|
|
// Chuyển sang nanosecond
|
|
uint64_t nanoseconds = t.toNSec();
|
|
|
|
// Khởi tạo từ giây
|
|
t.fromSec(1234567890.123456789);
|
|
|
|
// Khởi tạo từ nanosecond
|
|
t.fromNSec(1234567890123456789ULL);
|
|
```
|
|
|
|
#### So sánh
|
|
|
|
```cpp
|
|
robot::WallTime t1 = robot::WallTime::now();
|
|
robot::WallDuration d(1.0);
|
|
robot::WallTime t2 = t1 + d;
|
|
|
|
// So sánh
|
|
bool is_equal = (t1 == t2); // false
|
|
bool is_less = (t1 < t2); // true
|
|
bool is_greater = (t1 > t2); // false
|
|
bool is_less_equal = (t1 <= t2); // true
|
|
bool is_greater_equal = (t1 >= t2); // false
|
|
```
|
|
|
|
#### Phép toán với WallDuration
|
|
|
|
```cpp
|
|
robot::WallTime t = robot::WallTime::now();
|
|
robot::WallDuration d(5.0);
|
|
|
|
// Cộng duration
|
|
robot::WallTime future = t + d;
|
|
|
|
// Trừ duration
|
|
robot::WallTime past = t - d;
|
|
|
|
// Trừ hai WallTime để được WallDuration
|
|
robot::WallDuration elapsed = future - t;
|
|
|
|
// Compound assignment
|
|
t += d; // t = t + d
|
|
t -= d; // t = t - d
|
|
```
|
|
|
|
#### Kiểm tra giá trị
|
|
|
|
```cpp
|
|
robot::WallTime t;
|
|
|
|
// Kiểm tra có phải zero không
|
|
bool is_zero = t.isZero(); // true
|
|
|
|
// Kiểm tra các giá trị đặc biệt
|
|
bool is_max = (t == robot::WallTime::MAX);
|
|
bool is_min = (t == robot::WallTime::MIN);
|
|
bool is_zero_const = (t == robot::WallTime::ZERO);
|
|
```
|
|
|
|
### Constants
|
|
|
|
```cpp
|
|
robot::WallTime::MAX // Giá trị lớn nhất
|
|
robot::WallTime::MIN // Giá trị nhỏ nhất
|
|
robot::WallTime::ZERO // Zero (0, 0)
|
|
robot::WallTime::UNINITIALIZED // Uninitialized (0, 0)
|
|
```
|
|
|
|
## So sánh với `Time`
|
|
|
|
| Đặc điểm | `Time` | `WallTime` |
|
|
|----------|--------|------------|
|
|
| Nguồn thời gian | Simulated hoặc wall-clock | Luôn wall-clock |
|
|
| Cần khởi tạo | Có (`Time::init()`) | Không |
|
|
| Có thể throw exception | Có (nếu chưa init) | Không |
|
|
| Ảnh hưởng bởi sim time | Có | Không |
|
|
| Dùng trong ROS messages | Nên dùng | Không nên |
|
|
| Đo thời gian thực thi | Không phù hợp | Phù hợp |
|
|
| Timeout thực tế | Không phù hợp | Phù hợp |
|
|
| Logging với timestamp | Có thể | Phù hợp |
|
|
|
|
## Use Cases
|
|
|
|
### 1. Đo thời gian thực thi (Profiling/Benchmarking)
|
|
|
|
```cpp
|
|
// Đo thời gian thực thi của một hàm
|
|
robot::WallTime start = robot::WallTime::now();
|
|
|
|
// Thực hiện công việc
|
|
doSomething();
|
|
|
|
robot::WallTime end = robot::WallTime::now();
|
|
robot::WallDuration elapsed = end - start;
|
|
|
|
std::cout << "Thời gian thực thi: " << elapsed.toSec() << " giây" << std::endl;
|
|
```
|
|
|
|
**Ví dụ thực tế từ codebase:**
|
|
```cpp
|
|
// Trong clear_costmap_recovery.cpp
|
|
robot::WallTime t0 = robot::WallTime::now();
|
|
clear(global_costmap_);
|
|
ROS_DEBUG("Global costmap cleared in %fs",
|
|
(robot::WallTime::now() - t0).toSec());
|
|
```
|
|
|
|
### 2. Timeout và thời gian chờ
|
|
|
|
```cpp
|
|
// Đặt timeout cho một thao tác
|
|
robot::WallTime start = robot::WallTime::now();
|
|
robot::WallDuration timeout(5.0); // 5 giây
|
|
|
|
while (!operation_complete)
|
|
{
|
|
if (robot::WallTime::now() - start > timeout)
|
|
{
|
|
std::cout << "Timeout!" << std::endl;
|
|
break;
|
|
}
|
|
|
|
// Thực hiện công việc
|
|
doWork();
|
|
|
|
// Sleep một chút
|
|
robot::WallDuration(0.1).sleep();
|
|
}
|
|
```
|
|
|
|
### 3. Logging với timestamp thực
|
|
|
|
```cpp
|
|
void logMessage(const std::string& msg)
|
|
{
|
|
robot::WallTime now = robot::WallTime::now();
|
|
std::cout << "[" << now.toSec() << "] " << msg << std::endl;
|
|
}
|
|
```
|
|
|
|
### 4. Giao tiếp với hardware
|
|
|
|
```cpp
|
|
// Giao tiếp với hardware cần timing chính xác
|
|
robot::WallTime last_update = robot::WallTime::now();
|
|
robot::WallDuration update_interval(0.02); // 50Hz
|
|
|
|
while (running)
|
|
{
|
|
// Cập nhật hardware
|
|
updateHardware();
|
|
|
|
// Đợi đến lần cập nhật tiếp theo
|
|
robot::WallTime next_update = last_update + update_interval;
|
|
robot::WallTime::sleepUntil(next_update);
|
|
last_update = robot::WallTime::now();
|
|
}
|
|
```
|
|
|
|
### 5. Performance monitoring
|
|
|
|
```cpp
|
|
class PerformanceMonitor
|
|
{
|
|
private:
|
|
robot::WallTime start_time_;
|
|
std::vector<robot::WallDuration> measurements_;
|
|
|
|
public:
|
|
void start()
|
|
{
|
|
start_time_ = robot::WallTime::now();
|
|
}
|
|
|
|
void record()
|
|
{
|
|
robot::WallTime now = robot::WallTime::now();
|
|
robot::WallDuration elapsed = now - start_time_;
|
|
measurements_.push_back(elapsed);
|
|
start_time_ = now;
|
|
}
|
|
|
|
double getAverageTime()
|
|
{
|
|
if (measurements_.empty()) return 0.0;
|
|
|
|
double total = 0.0;
|
|
for (const auto& d : measurements_)
|
|
{
|
|
total += d.toSec();
|
|
}
|
|
return total / measurements_.size();
|
|
}
|
|
};
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
### 1. Sử dụng WallTime cho đo đạc thời gian thực
|
|
|
|
```cpp
|
|
// ✅ ĐÚNG - Dùng WallTime để đo thời gian thực thi
|
|
robot::WallTime start = robot::WallTime::now();
|
|
processData();
|
|
robot::WallDuration elapsed = robot::WallTime::now() - start;
|
|
|
|
// ❌ SAI - Dùng Time có thể không chính xác trong simulation
|
|
robot::Time start = robot::Time::now();
|
|
processData();
|
|
robot::Duration elapsed = robot::Time::now() - start;
|
|
```
|
|
|
|
### 2. Sử dụng Time cho ROS messages
|
|
|
|
```cpp
|
|
// ✅ ĐÚNG - Dùng Time cho ROS messages
|
|
geometry_msgs::PoseStamped msg;
|
|
msg.header.stamp = robot::Time::now();
|
|
|
|
// ❌ SAI - Không nên dùng WallTime cho ROS messages
|
|
msg.header.stamp = robot::WallTime::now(); // Không tương thích
|
|
```
|
|
|
|
### 3. Kết hợp Time và WallTime
|
|
|
|
```cpp
|
|
// Sử dụng Time cho ROS operations
|
|
robot::Time ros_time = robot::Time::now();
|
|
publishMessage(msg);
|
|
|
|
// Sử dụng WallTime cho performance monitoring
|
|
robot::WallTime wall_start = robot::WallTime::now();
|
|
expensiveOperation();
|
|
robot::WallDuration wall_elapsed = robot::WallTime::now() - wall_start;
|
|
std::cout << "Operation took " << wall_elapsed.toSec() << " seconds" << std::endl;
|
|
```
|
|
|
|
### 4. Timeout với WallTime
|
|
|
|
```cpp
|
|
// ✅ ĐÚNG - Dùng WallTime cho timeout thực tế
|
|
robot::WallTime deadline = robot::WallTime::now() + robot::WallDuration(10.0);
|
|
while (robot::WallTime::now() < deadline)
|
|
{
|
|
if (tryOperation())
|
|
break;
|
|
robot::WallDuration(0.1).sleep();
|
|
}
|
|
```
|
|
|
|
## Ví dụ hoàn chỉnh
|
|
|
|
### Ví dụ 1: Đo thời gian thực thi của nhiều operations
|
|
|
|
```cpp
|
|
#include <robot/time.h>
|
|
#include <iostream>
|
|
#include <vector>
|
|
|
|
void benchmarkOperations()
|
|
{
|
|
std::vector<std::string> operations = {"operation1", "operation2", "operation3"};
|
|
|
|
for (const auto& op_name : operations)
|
|
{
|
|
robot::WallTime start = robot::WallTime::now();
|
|
|
|
// Thực hiện operation (giả lập)
|
|
performOperation(op_name);
|
|
|
|
robot::WallDuration elapsed = robot::WallTime::now() - start;
|
|
std::cout << op_name << " took " << elapsed.toSec() << " seconds" << std::endl;
|
|
}
|
|
}
|
|
```
|
|
|
|
### Ví dụ 2: Rate limiting với WallTime
|
|
|
|
```cpp
|
|
class RateLimiter
|
|
{
|
|
private:
|
|
robot::WallTime last_time_;
|
|
robot::WallDuration min_interval_;
|
|
|
|
public:
|
|
RateLimiter(double min_rate_hz)
|
|
: min_interval_(1.0 / min_rate_hz)
|
|
, last_time_(robot::WallTime::now())
|
|
{}
|
|
|
|
bool canProceed()
|
|
{
|
|
robot::WallTime now = robot::WallTime::now();
|
|
robot::WallDuration elapsed = now - last_time_;
|
|
|
|
if (elapsed >= min_interval_)
|
|
{
|
|
last_time_ = now;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
```
|
|
|
|
### Ví dụ 3: Timeout handler
|
|
|
|
```cpp
|
|
class TimeoutHandler
|
|
{
|
|
private:
|
|
robot::WallTime start_time_;
|
|
robot::WallDuration timeout_;
|
|
|
|
public:
|
|
TimeoutHandler(double timeout_seconds)
|
|
: timeout_(timeout_seconds)
|
|
, start_time_(robot::WallTime::now())
|
|
{}
|
|
|
|
bool isExpired() const
|
|
{
|
|
robot::WallTime now = robot::WallTime::now();
|
|
return (now - start_time_) > timeout_;
|
|
}
|
|
|
|
robot::WallDuration remaining() const
|
|
{
|
|
robot::WallTime now = robot::WallTime::now();
|
|
robot::WallDuration elapsed = now - start_time_;
|
|
robot::WallDuration remaining = timeout_ - elapsed;
|
|
return (remaining > robot::WallDuration(0)) ? remaining : robot::WallDuration(0);
|
|
}
|
|
|
|
void reset()
|
|
{
|
|
start_time_ = robot::WallTime::now();
|
|
}
|
|
};
|
|
```
|
|
|
|
## Tương thích với ROS
|
|
|
|
`robot::WallTime` được thiết kế để tương thích với `ros::WallTime` trong ROS. Các API và behavior đều giống nhau:
|
|
|
|
```cpp
|
|
// ROS
|
|
ros::WallTime t1 = ros::WallTime::now();
|
|
ros::WallDuration d = ros::WallDuration(1.0);
|
|
ros::WallTime t2 = t1 + d;
|
|
|
|
// robot_time (tương đương)
|
|
robot::WallTime t1 = robot::WallTime::now();
|
|
robot::WallDuration d = robot::WallDuration(1.0);
|
|
robot::WallTime t2 = t1 + d;
|
|
```
|
|
|
|
## Lưu ý quan trọng
|
|
|
|
1. **Không dùng WallTime cho ROS messages**: ROS messages yêu cầu `Time`, không phải `WallTime`
|
|
|
|
2. **Precision**: `WallTime` có độ chính xác nanosecond, nhưng độ chính xác thực tế phụ thuộc vào hệ thống
|
|
|
|
3. **Thread safety**: Tất cả operations của `WallTime` đều thread-safe
|
|
|
|
4. **Performance**: `WallTime::now()` rất nhanh, có thể gọi thường xuyên mà không lo về performance
|
|
|
|
5. **Cross-platform**: Hoạt động trên cả Linux và Windows
|
|
|
|
## Tài liệu tham khảo
|
|
|
|
- `README.md` - Tổng quan về thư viện robot_time
|
|
- `time.h` - Header file với API đầy đủ
|
|
- ROS Documentation: http://docs.ros.org/en/diamondback/api/rostime/html/classros_1_1WallTime.html
|
|
|