11. 时间 Time / Rate / Timer
时间相关能力:Time / Duration / Rate / Clock 用于时间戳与稳频;Timer / TimerComponent 用于周期任务。
本文 §11 |
相关文档 |
|---|---|
时间与定时 |
模块 |
头文件 |
用途 |
|---|---|---|
Time / Duration |
|
时间戳、间隔、睡眠 |
Rate |
|
主循环稳频 |
Clock |
|
系统 / Mock 时钟 |
Timer |
|
时间轮周期回调 |
TimerComponent |
|
DAG 周期 |
11.1 Time / Duration
Time — 时间点
内部以 纳秒(uint64_t)存储,对标 ROS rclcpp::Time。
#include "autolink/time/time.hpp"
using autolink::Time;
using autolink::Duration;
// 当前墙钟时间(经 Clock 单例,默认同系统时间)
Time now = Time::Now();
uint64_t ns = now.ToNanosecond();
double sec = now.ToSecond();
// 单调时钟(不受 NTP 调整影响,适合测间隔)
Time mono = Time::MonoTime();
// 构造:纳秒 / 秒 / 秒+纳秒
Time t1(1234567890ULL);
Time t2(1.5); // 1.5 秒
Time t3(2, 500000000); // 2s + 500ms
// 睡眠至指定时刻
Time::SleepUntil(now + Duration(1.0));
消息时间戳(talker.cpp、service.cpp 等):
msg->set_timestamp(Time::Now().ToNanosecond());
Duration — 时间间隔
Duration d1(100000000); // 100ms(纳秒)
Duration d2(0.5); // 0.5 秒
Duration d3(1, 0); // 1 秒
d2.Sleep(); // 阻塞当前线程 0.5s
Time t = Time::Now();
Time t2 = t + d2;
Time t3 = t - d1;
Duration elapsed = t2 - t; // 两 Time 相减得 Duration
API |
说明 |
|---|---|
|
单位转换 |
|
是否为 0 |
|
阻塞睡眠 |
|
间隔运算 |
11.2 Rate
Rate 在循环末尾调用 Sleep(),自动扣除本轮已耗时间,使平均频率趋近目标值。适合 Binary 模式主循环稳频发布。
#include "autolink/time/rate.hpp"
using autolink::Rate;
Rate rate(1.0); // 1 Hz
// Rate rate(100ms_as_nanoseconds);
// Rate rate(Duration(0.5)); // 2 Hz
while (autolink::OK()) {
writer->Write(msg);
rate.Sleep(); // 睡至下一周期边界
}
talker.cpp 完整片段:
#include "autolink/time/rate.hpp"
#include "autolink/time/time.hpp"
Rate rate(1.0);
uint64_t seq = 0;
while (autolink::OK()) {
auto msg = std::make_shared<Chatter>();
msg->set_timestamp(Time::Now().ToNanosecond());
msg->set_seq(seq++);
talker->Write(msg);
rate.Sleep();
}
API |
说明 |
|---|---|
|
目标频率(Hz) |
|
目标周期(纳秒) |
|
由间隔构造 |
|
等待至下一周期 |
|
重置起始时刻 |
|
上一轮实际周期 |
|
期望周期 |
若单轮 Write + 处理超过期望周期,Sleep() 立即返回,不会累积负睡眠。
11.3 Clock
Clock 单例统一 Time::Now() 的数据源,支持 系统时钟 与 Mock 时钟(仿真 / 单测)。
#include "autolink/time/clock.hpp"
using autolink::Clock;
using autolink::proto::ClockMode;
// 默认 MODE_AUTOLINK:系统墙钟
Time t = Clock::Now();
double s = Clock::NowInSeconds();
// 仿真 / 测试:切换 Mock 并手动推进
Clock::SetMode(ClockMode::MODE_MOCK);
Clock::SetNow(Time(1000.0));
Clock::SetNowInSeconds(1001.5);
|
含义 |
|---|---|
|
系统时间(默认) |
|
由 |
run_mode_conf.proto 中 RunModeConf.clock_mode 可在配置层指定;RunMode::MODE_SIMULATION 常与 Mock 时钟联用。
11.4 Timer
基于 时间轮(timing_wheel.hpp),周期单位 毫秒,与 Time/Rate 独立。
#include "autolink/timer/timer.hpp"
struct TimerOption {
uint32_t period; // ms,范围 1 ~ 512*64
std::function<void()> callback;
bool oneshot; // true=单次,false=周期
};
autolink::Timer timer(100, []() { AINFO << "tick"; }, false);
timer.Start();
// ...
timer.Stop();
亦可先默认构造再 SetOption:
Timer t;
t.SetOption(TimerOption(50, callback, false));
t.Start();
回调在时间轮线程触发,不在 Reader 回调线程;仍不宜执行过重逻辑。
11.5 TimerComponent
继承 TimerComponent,实现无参 Proc(),由 DAG interval(ms)驱动:
头文件(timer_component_example.hpp):
class TimerComponentSample : public TimerComponent {
public:
bool Init() override;
bool Proc() override;
private:
std::shared_ptr<Writer<Driver>> driver_writer_ = nullptr;
};
AUTOLINK_REGISTER_COMPONENT(TimerComponentSample)
实现(timer_component_example.cpp):
bool TimerComponentSample::Init() {
driver_writer_ = node_->CreateWriter<Driver>("/carstatus/channel");
return true;
}
bool TimerComponentSample::Proc() {
static int i = 0;
auto out_msg = std::make_shared<Driver>();
out_msg->set_msg_id(i++);
driver_writer_->Write(out_msg);
return true;
}
DAG(timer.dag),interval 单位为 ms:
timer_components {
class_name : "TimerComponentSample"
config {
name : "timer"
interval : 10
}
}
mainboard -d autolink/examples/cpp/timer_component_example/timer.dag
11.6 机制对比
机制 |
线程模型 |
典型场景 |
示例 |
|---|---|---|---|
|
— |
消息时间戳、超时判断 |
|
|
阻塞当前线程 |
简单延时 |
|
|
阻塞当前线程,补偿耗时 |
Binary 主循环稳频 |
|
|
时间轮回调线程 |
独立周期任务 |
辅助逻辑 |
|
Scheduler 调度 |
无输入周期发布 |
|
Component 体系内周期任务优先 TimerComponent;Binary 工具用 Rate;仅需时间戳用 Time,无需 Timer。
11.7 Python API(Time / Rate)
autolink_py3.autolink_time(或 from autolink_py3 import autolink_time)提供与 C++ 对等的 Time / Duration / Rate。
Time(py_time.py):
from autolink_py3 import autolink_time
ct = autolink_time.Time(123)
print(ct.to_nsec())
# 墙钟
ftime = autolink_time.Time.now().to_sec()
# 单调时钟
mtime = autolink_time.Time.mono_time().to_sec()
# 运算
td1 = autolink_time.Duration(111)
tm1 = ct - td1
tm5 = autolink_time.Time(1.8)
Duration:
td1 = autolink_time.Duration(111) # 纳秒
td2 = autolink_time.Duration(601000000000)
td3 = td2 - td1
print(td2.to_sec(), td2.iszero())
td5 = autolink_time.Duration(1.8) # 秒
Rate(py_talker.py 稳频发布):
rate = autolink_time.Rate(1.0) # 1 Hz
# rate = autolink_time.Rate(0.2) # 0.2 Hz
# rate = autolink_time.Rate(autolink_time.Duration(666))
while not autolink.is_shutdown():
msg.timestamp = autolink_time.Time.now().to_nsec()
writer.write(msg)
rate.sleep()
运行示例:
python3 autolink/examples/python/py_time.py
11.8 Python API(Timer)
autolink_py3.timer 对应 C++ Timer(py_timer.py):
from autolink_py3 import timer as autolink_timer
def fun():
print("cb fun is called:", count)
autolink.init()
ct = autolink_timer.Timer(10, fun, 0) # 10ms, oneshot=0 表周期
ct.start()
time.sleep(1)
ct.stop()
ct2 = autolink_timer.Timer()
ct2.set_option(10, fun, 0)
ct2.start()
11.9 选型
需求 |
推荐 |
|---|---|
消息打时间戳 |
|
测执行耗时 |
|
Binary 稳频发布 |
|
仿真 / 单测时间 |
|
周期发布、无输入 channel |
TimerComponent + DAG |
独立周期回调 |
|
多路传感器对齐 |