robot_time/WALLTIME_USAGE.md

12 KiB

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

// 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

// 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

// 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).

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.

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ề trueWallTime luôn sử dụng system time.

bool is_system = robot::WallTime::isSystemTime();  // Luôn là true

Methods kế thừa từ TimeBase

Chuyển đổi đơn vị

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

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

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ị

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

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 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)

// Đ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:

// 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ờ

// Đặ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

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

// 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

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

// ✅ ĐÚ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

// ✅ ĐÚ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

// 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

// ✅ ĐÚ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

#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

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

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:

// 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