ROS2通信机制额外内容(2)


1.时间相关API

为什么要有时间相关API呢?我们使用机器人建图的时候,需要的数据肯定是实时的,不能有延迟。如果我当前位置的信息,几秒后才能接收到,那么是非常危险的!所以有了事件相关API就能较好地解决这些问题!

准备工作:
创建一个功能包
在这里插入图片描述

1.1 API_Rate

在前面写的话题通信案例中, 要求话题发布方按照一定的频率发布消息, 我们实现时是通过定时器来控制发布频率的, 其实, 除了定时器之外, ROS2 中还提供了 Rate 类, 通过该类对象也可以控制程序的运行频率。

示例: 周期性输出一段文本。

//1.包含头文件;
#include "rclcpp/rclcpp.hpp"
using namespace std::chrono_literals;//使用该命名空间
//3.自定义节点类;
class MyNode:public rclcpp::Node{
public:
    MyNode():Node("time_node_cpp"){
    demo_rate();
  }
private:
//演示Rate的使用
    void demo_rate()
    {
      //1.创建Rate对象
      rclcpp::Rate rate1(500ms);//设置休眠时间,500ms休眠一次
      rclcpp::Rate rate2(1);//设置执行频率,1s一次
      //2.调用Rate的sleep函数
      while(rclcpp::ok())
      {
        RCLCPP_INFO(this->get_logger(),"RateAPI测试!");
        rate1.sleep();
        //rate2.sleep();
      }
    }
};

int main(int argc, char const *argv[])
{
    //2.初始化ROS2客户端;
    rclcpp::init(argc,argv);
    //4.调用spain汉书,并传入节点对象指针;
    rclcpp::spin(std::make_shared<MyNode>());
    //5.资源释放
    rclcpp::shutdown();
    return 0;
}

在这里插入图片描述

rate1.sleep();//这个就是一秒两次输出日志
rate2.sleep();//这个就是一秒一次输出日志

1.2 API_Time

示例: 创建 Time 对象, 并调用其函数。(时间转化,纳秒与秒转化)

//1.包含头文件;
#include "rclcpp/rclcpp.hpp"
using namespace std::chrono_literals;
//3.自定义节点类;
class MyNode:public rclcpp::Node{
public:
    MyNode():Node("time_node_cpp"){
    demo_time();
  }
private:
//演示Time的使用
void demo_time()
{
  //1.创建Time对象
  rclcpp::Time t1(500000000L);//传入纳秒,1s=10亿纳秒
  rclcpp::Time t2(2,500000000L);//传入秒和纳秒
  // rclcpp::Time right_now=this->get_clock()->now();//第一种方式
  rclcpp::Time right_now = this->now();//通过节点获取当前时刻,第二种方式

  //2.调用Time对象的函数
  RCLCPP_INFO(this->get_logger(),"s=%.2f,ns=%ld",t1.seconds(),t1.nanoseconds());
  RCLCPP_INFO(this->get_logger(),"s=%.2f,ns=%ld",t2.seconds(),t2.nanoseconds());
  RCLCPP_INFO(this->get_logger(),"s=%.2f,ns=%ld",right_now.seconds(),right_now.nanoseconds());
  //seconds是以秒获取时刻,nanoseconds是以纳秒获取时刻,纳秒是长整型
}
};

int main(int argc, char const *argv[])
{
    //2.初始化ROS2客户端;
    rclcpp::init(argc,argv);
    //4.调用spain汉书,并传入节点对象指针;
    rclcpp::spin(std::make_shared<MyNode>());
    //5.资源释放
    rclcpp::shutdown();
    return 0;
}

在这里插入图片描述

1.3 API_Duration

示例: 创建 Duration 对象, 并调用其函数。(时间转化,纳秒与秒转化)

//1.包含头文件;
#include "rclcpp/rclcpp.hpp"
using namespace std::chrono_literals;
//3.自定义节点类;
class MyNode:public rclcpp::Node{
public:
    MyNode():Node("time_node_cpp"){
    demo_duration();
  }
private:
//演示Duration的使用
void demo_duration()
{
  //1.创建Duration对象
  rclcpp::Duration du1(1s);
  rclcpp::Duration du2(2,500000000);
  //2.调用函数
  RCLCPP_INFO(this->get_logger(),"s=%.2f,ns=%ld",du1.seconds(),du1.nanoseconds());
  RCLCPP_INFO(this->get_logger(),"s=%.2f,ns=%ld",du2.seconds(),du2.nanoseconds());
}
  
};

int main(int argc, char const *argv[])
{
    //2.初始化ROS2客户端;
    rclcpp::init(argc,argv);
    //4.调用spain汉书,并传入节点对象指针;
    rclcpp::spin(std::make_shared<MyNode>());
    //5.资源释放
    rclcpp::shutdown();
    return 0;
}

在这里插入图片描述

1.4 API_Time和API_Duration的区别

在这里插入图片描述

1.5 Time 与 Duration 运算

//1.包含头文件;
#include "rclcpp/rclcpp.hpp"
using namespace std::chrono_literals;
//3.自定义节点类;
class MyNode:public rclcpp::Node{
public:
    MyNode():Node("time_node_cpp"){
    //demo_time();
    //demo_duration();
    demo_opt();
  }
private:
//演示运算符的使用
void demo_opt()
{
    rclcpp::Time t1(10,0);
    rclcpp::Time t2(30,0);

    rclcpp::Duration du1(8,0);
    rclcpp::Duration du2(17,0);

    // 比较
RCLCPP_INFO(this->get_logger(),"t1 >= t2 ? %d",t1 >= t2);
RCLCPP_INFO(this->get_logger(),"t1 < t2 ? %d",t1 < t2);
// 数学运算
rclcpp::Time t3 = t2 + du1;
rclcpp::Time t4 = t1 - du1;
rclcpp::Duration du3 = t2 - t1;
RCLCPP_INFO(this->get_logger(), "t3 = %.2f",t3.seconds());
RCLCPP_INFO(this->get_logger(), "t4 = %.2f",t4.seconds());
RCLCPP_INFO(this->get_logger(), "du3 = %.2f",du3.seconds());
RCLCPP_INFO(this->get_logger(),"--------------------------------------");
// 比较
RCLCPP_INFO(this->get_logger(),"du1 >= du2 ? %d", du1 >= du2);
RCLCPP_INFO(this->get_logger(),"du1 < du2 ? %d", du1 < du2);
// 数学运算
rclcpp::Duration du4 = du1 * 3.0;
rclcpp::Duration du5 = du1 + du2;
rclcpp::Duration du6 = du1 - du2;
RCLCPP_INFO(this->get_logger(), "du4 = %.2f",du4.seconds());
RCLCPP_INFO(this->get_logger(), "du5 = %.2f",du5.seconds());
RCLCPP_INFO(this->get_logger(), "du6 = %.2f",du6.seconds());
}


//演示Duration的使用
void demo_duration()
{
  //1.创建Duration对象
  rclcpp::Duration du1(1s);
  rclcpp::Duration du2(2,500000000);
  //2.调用函数
  RCLCPP_INFO(this->get_logger(),"s=%.2f,ns=%ld",du1.seconds(),du1.nanoseconds());
  RCLCPP_INFO(this->get_logger(),"s=%.2f,ns=%ld",du2.seconds(),du2.nanoseconds());
}

//演示Time的使用
void demo_time()
{
  //1.创建Time对象
  rclcpp::Time t1(500000000L);
  rclcpp::Time t2(2,500000000L);
  // rclcpp::Time right_now=this->get_clock()->now();
  rclcpp::Time right_now = this->now();

  //2.调用Time对象的函数
  RCLCPP_INFO(this->get_logger(),"s=%.2f,ns=%ld",t1.seconds(),t1.nanoseconds());
  RCLCPP_INFO(this->get_logger(),"s=%.2f,ns=%ld",t2.seconds(),t2.nanoseconds());
  RCLCPP_INFO(this->get_logger(),"s=%.2f,ns=%ld",right_now.seconds(),right_now.nanoseconds());
}

};

int main(int argc, char const *argv[])
{
    //2.初始化ROS2客户端;
    rclcpp::init(argc,argv);
    //4.调用spain汉书,并传入节点对象指针;
    rclcpp::spin(std::make_shared<MyNode>());
    //5.资源释放
    rclcpp::shutdown();
    return 0;
}

在这里插入图片描述

2.通信机制工具

一个完整的机器人系统启动之后,其组成是比较复杂的,可能包含十几个、几十个甚至上百个节点,不同的节点可能又包含一个或多个通信对象(话题发布方、话题订阅方、服务端、客户端、动作服务端、动作客户端、参数服务端、参数客户端),通信时还需要使用到各种各样的msg、srv或action接口消息,那么在开发过程中,如何才能方便的获取这些节点、话题、服务、动作、参数以及接口相关的信息呢?

编写通信实现,通信至少涉及到双方,一方编写完毕后,如何验证程序是否可以正常运行呢?

话题通信过程中,发布方程序中设置了消息的发布频率,如何判断实际运行中的发布频率是否和设置的频率一致呢?

这些就取决于我们的通信机制工具了!!!

2.1 命令工具

ROS2中常用的命令如下:

ros2 node:节点相关命令行工具

ros2 interface:接口(msg、srv、action)消息相关的命令行工具

ros2 topic:话题通信相关的命令行工具

ros2 service:服务通信相关的命令行工具

ros2 action:动作通信相关的命令行工具

ros2 param:参数服务相关的命令行工具

关于命令的使用一般都会提供帮助文档,帮助文档的获取方式如下:
①可以通过命令 -h 或 命令 --help的方式查看命令帮助文档,比如:ros2 node -h或 ros2 node --help。
②命令下参数的使用也可以通过命令 参数 -h 或 命令 参数 --help的方式查看帮助文档,比如:ros2 node list -h或 ros2 node list --help。

在这里插入图片描述
一些常用的命令功能如下:
在这里插入图片描述

2.2 rqt工具箱

rqt工具箱是ROS里面一种可视化工具,使用非常方便!

常用的rqt启动命令有:
方式1:rqt
方式2:ros2 run rqt_gui rqt_gui

预备工作:打开我们的小乌龟和键盘控制
在这里插入图片描述

下面简单列举几种功能:
1.查看话题和相关节点信息之间的关联(graph):
在这里插入图片描述
2.添加topic插件并发送速度指令控制乌龟运动

在这里插入图片描述
3.添加 service 插件并发送请求,在制定位置生成一只乌龟。
在这里插入图片描述
4.通过参数插件动态修改乌龟窗体背景颜色。
在这里插入图片描述
当然rqt的功能远不仅仅如此!

  • 19
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Chris·Bosh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值