ROS时间概念总结:ros::Time、ros::Duration、定时器ros::Timer&ros::Rate

0. 写于最前面

希望大家收藏:

本文持续更新地址:https://haoqchen.site/2018/11/08/ROS-time/

本文总结了一些ROS中常用到的时间相关的一些类、定时器、概念等。

我的另外一篇博文整理了Linux下时间相关的大部分函数,感兴趣的可以看一下:https://haoqchen.site/2019/12/17/linux-time-summary/

作者会长期更新自己学到的一些知识,有什么错误希望大家能够一起探讨,一起进步。喜欢的话点个赞呗。

左侧专栏还在更新其他ROS实用技巧哦,关注一波?

1. 概述

roslib给用户提供了ros::Time and ros::Duration两个类来描述时刻以及时间间隔两个概念,其中Duration可以是负数。Time和Duration拥有一样的成员:
int32 sec
int32 nsec

一般情况下,这里的时间都是跟平台(即系统)的时间相关联的,但ROS提供了一种模拟时钟即ROS时钟时间,当进行了相应设置时,这里的时间就是ROS时钟时间。

2. 时间与时间间隔的基本使用

2.1 获得当前时间

ros::Time begin = ros::Time::now();
注:如果使用的是模拟时间,now在/clock话题接收到第一个消息之前都会返回0


2.2 定义类对象

ros::Time::Time(uint32_t _sec, uint32_t _nsec)
ros::Time::Time(double t)

ros::Duration::Duration(uint32_t _sec, uint32_t _nsec)
ros::Duration::Duration(double t)

_sec是秒,_nsec是纳秒
故ros::Time a_little_after_the_beginning(0, 1000000);等价于ros::Time a_little_after_the_beginning(0.001);

2.3 相互转化、比较

Time继承自
template<class T, class D>
class ros::TimeBase< T, D >

Duration继承自
template<class T>
class ros::DurationBase< T >

两个基类都实现了>、<、!=等比较符。并且两者都实现了
uint64_t     toNSec () const
double     toSec () const
我们可以通过这两个函数来进行Time和Duration的转化

2.4 运算符

两个基类都重载了+、-、+=、-=运算符:

1 hour + 1 hour = 2 hours (duration + duration = duration)

2 hours - 1 hour = 1 hour (duration - duration = duration)

Today + 1 day = tomorrow (time + duration = time)

Today - tomorrow = -1 day (time - time = duration)

Today + tomorrow = error (time + time is undefined)

3. 延时与循环

bool ros::Duration::sleep()
ros::Duration(0.5).sleep(); // sleep for half a second

4. 定时器

ros::Timer

首先需要说明的是,ROS并不是实时系统,所以定时器并不能确保精确定时。精确的执行时间以及理论上应该执行的时间可以在回调函数的ros::TimerEvent结构中得到。

ros::Timer ros::NodeHandle::createTimer(ros::Duration period, <callback>, bool oneshot = false);
ros::Timer timer = n.createTimer(ros::Duration(0.1), timerCallback);//定时0.1s
void timerCallback(const ros::TimerEvent& e);

其中oneshot是定义是否只定时一次,默认连续定时。这里也不一定要回调函数,也可以传函数对象等,这里不细述。

其中TimerEvent结构体定义如下:

struct TimerEvent
{
  Time last_expected;                     ///< In a perfect world, this is when the last callback should have happened
  Time last_real;                         ///< When the last callback actually happened

  Time current_expected;                  ///< In a perfect world, this is when the current callback should be happening
  Time current_real;                      ///< This is when the current callback was actually called (Time::now() as of the beginning of the callback)

  struct
  {
    WallDuration last_duration;           ///< How long the last callback ran for, always in wall-clock time
  } profile;
};

ros::Rate

ros::Rate r(10); // 10 hz
while (ros::ok())
{
//... do some work ...
    bool met = r.sleep();
}

它的功能就是先设定一个频率,然后通过睡眠度过一个循环中剩下的时间,来达到该设定频率。如果能够达到该设定频率则返回true,不能则返回false。

计时的起点是上一次睡眠的时间、构造函数被调用、或者调用void ros::Rate::reset()函数重置时间。

因为没有TimerEvent,所以相对于Timer而言,Rate的精确度会有所下降。

参考

http://wiki.ros.org/roscpp/Overview/Time

http://wiki.ros.org/roscpp_tutorials/Tutorials/Timers

http://docs.ros.org/diamondback/api/rostime/html/classros_1_1Rate.html

ROS2中,std::make_unique函数用于创建一个唯一指针。它是C++14中引入的一个函数模板,用于在堆上创建一个对象,并返回一个指向该对象的唯一指针。在ROS2中,可以使用std::make_unique函数来创建ROS2节点。例如,可以使用以下代码创建一个继承自rclcpp::Node的类的实例: ```cpp auto node = std::make_unique<MinimalPublisher>(); ``` 这将创建一个MinimalPublisher类的实例,并返回一个指向该实例的唯一指针。然后,可以使用该指针来访问该节点的成员函数和变量。 引用: \[1\] 截至目前,galactic虽然对以上过程进行了一定程度的封装,但封装也极为简化,同时read的流程仍没有封装,使用还是很麻烦。节点的建立ROS2使用了完全的面向对象设计,以C++为例,大量的ROS API都封装在了rclcpp::Node这个类中,也就意味着需要使用这些API,你必须定义一个继承自Node的类,这也就强制用户必须使用类的方式构建整个系统,官方的一个简单的例子如下:class MinimalPublisher : public rclcpp::Node { public: MinimalPublisher() : Node("minimal_publisher"), count_(0) { publisher_ = this->create_publisher<std_msgs::msg::String>("topic", 10); timer_ = this->create_wall_timer( 500ms, std::bind(&MinimalPublisher::timer_callback, this)); } private: rclcpp::TimerBase::SharedPtr timer_; rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_; size_t count_; } \[2\] 只要在同一ID的机器就可以接受到彼此的消息。yaml配置文件比较坑的一个细节,ROS2在yaml使用上有两个变化,如下:test_node: ros__parameters: common: topic: "your_topic" \[3\] 主要是下面三个部分:名称重定向日志配置参数使用命令行传参在eloquent之后需要加 --ros-args标志,dashing版本不需要eloquent:ros2 run my_package node_executable --ros-args ... #### 引用[.reference_title] - *1* *2* [ROS2实践总结](https://blog.csdn.net/liu3612162/article/details/121906612)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [[ros2学习]-学习ROS 2工具集](https://blog.csdn.net/weixin_36628778/article/details/106375420)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值