常用API之C++

本文介绍了ROS(Robot Operating System)的初始化过程,包括创建节点、设置匿名名称避免重名,以及如何使用话题与服务创建发布者对象,涉及latch选项的应用。此外,还详细讲解了回调函数的使用,如ros::spin()和ros::spinOnce(),以及时间相关操作,包括计时器、定时任务和时间计算。
摘要由CSDN通过智能技术生成

1. 初始化:

//2.初始化ROS节点
/*
    作用:ROS初始化函数
    参数:
        1. argc    ----封装实参个数(n+1
        2. argv    ----封装参数的数组
        3. name    ----为节点命名(唯一性)
        4. options ----节点启动选项

        返回值:void
        
    使用:
        1. argc  argv
            如果按照ROS中的特定格式传入实参,那么ROS可以加以使用,比如用来设置全局参数、给节点重命名
        2. option 的使用
            节点名称需要保证唯一,会导致一个问题:同一个节点不能重复启动。
            结果:ROS中当有重名的节点启动时,之前的节点会被关闭。
            需求:特定场景下,需要一个节点多次启动且能正常运行,怎么办?
            解决:设置启动项 ros::init_options::AnonymousName
                    当创建ROS节点时,会在用户自定义的节点名称后缀随机数,从而避免重名问题

*/

视频讲解:https://www.bilibili.com/video/BV1Ci4y1L7ZZ?p=125&spm_id_from=pageDriver

2. 话题与服务相关对象

    //4.创建发布者对象
    作用:创建发布者对象

    模板:被发布的消息的类型

    参数:
        1.话题名称
        2.队列长度
        3.latch(可选)  如果设置为true,会保存发布方的最后一条消息,并且
               新的订阅对象连接到发布方时,发布方会将这条消息发送给订阅者
    使用:
        latch 设置为 true 的作用:
        以静态地图发布为例,方案1:可以使用规定频率发送地图数据,但是效率低;方案二:可以将
        地图发布对象的 latch 设置为 true ,并且发布方只发送一条数据,每当订阅者连接时,
        将地图数据发送给订阅者(只发送一次),这样提高了数据的发送效率。

视频讲解:https://www.bilibili.com/video/BV1Ci4y1L7ZZ?p=126&spm_id_from=pageDriver

3. 回调函数

ros::spin()ros::spinOnce() 两个回旋函数,可以用于处理回调函数。

相同点: 二者都用于处理回调函数;

不同点: ros::spin() 是进入了循环执行回调函数,而 ros::spinOnce() 只会执行一次回调函数(没有循环),在 ros::spin() 后的语句不会执行到,而 ros::spinOnce() 后的语句可以执行。

4. 时间

注意:
创建:nh.createTimer( )
参数1:时间间隔
参数2:回调函数(时间事件 TimeEvent)
参数3:是否只执行1次
参数4:是否自动启动(当设置为 false ,需要手动调用 timer.start() )
定时器启动后:ros::spin()

#include "ros/ros.h"
/*
    需求1:演示时间相关的操作(获取当前时刻 + 设置制定时刻)
    实现:
        1.准备(头文件、节点初始化、NodeHandle创建...)
        2.获取当前时刻
        3.设置指定时刻

    需求2 程序执行中停顿5
    实现:
        1.创建持续时间对象
        2.休眠
    
    需求3:已知程序开始运行的时刻,和程序运行的时间,求运行结束的时刻
    实现:
        1.获取开始执行的时刻
        2.模拟运行时间(N秒)
        3.计算结束时刻 = 开始 + 持续时间
    注意:
        1.时刻与持续时间可以执行加减
        2.持续时间之间也可以执行加减
        3.时刻之间值可以相减不可相加

    需求4:每隔一秒,再控制台输出一段文本
    实现:
        策略1:ros::Rate()
        策略2:定时器

*/
    //后面定时器中的回调函数:
    void cb(const ros::TimerEvent& event){
        ROS_INFO("----------------------");
    }

int main(int argc, char *argv[])
{
    // 1.准备(头文件、节点初始化、NodeHandle创建...)
    setlocale(LC_ALL,"");
    ros::init(argc,argv,"hello_time");
    ros::NodeHandle nh; //注:必须有这一步,否则会导致时间API调用失败(再NodeHandle会初始化时间操作)
    // 2.获取当前时刻
    //now 函数会将当前时刻封装并返回
    //当前时刻:now 被调用执行的那一刻
    //参考系:1970 0101 000000
    ros::Time right_now = ros::Time::now();
    ROS_INFO("当前时刻:%.2f",right_now.toSec());
    ROS_INFO("当前时刻:%d",right_now.sec);
    // 3.设置指定时刻
    ros::Time t1(20,3123456789);  //逗号(秒,纳秒)
    ros::Time t2(100.35);         //(浮点类型)
    ROS_INFO("t1 = %.2f",t1.toSec());
    ROS_INFO("t2 = %.2f",t2.toSec());

    //---------------------------------------------------------------------
    ROS_INFO("------------------------持续时间---------------------------");
    ros::Time start = ros::Time::now();
    ROS_INFO("开始休眠:%.2f",start.toSec());

    //核心
    ros::Duration du(4.5);
    du.sleep();//休眠

    ros::Time end = ros::Time::now();
    ROS_INFO("休眠结束:%.2f",end.toSec());
    
    //---------------------------------------------------------------------
    ROS_INFO("------------------------时间运算---------------------------");
    //时刻与持续时间运算
    //1.获取开始执行的时刻
    ros::Time begin = ros::Time::now();
    //2.模拟运行时间(N秒)
    ros::Duration du1(5);
    //3.计算结束时刻 = 开始 + 持续时间
    ros::Time stop = begin + du1;  //也可以减法运算
    ROS_INFO("开始时刻:%.2f",begin.toSec());
    ROS_INFO("结束时刻:%.2f",stop.toSec());

    //时刻与时刻运算
    // ros::Time sun = begin + stop;   //不可以相加,会抛异常
    ros::Duration du2 = begin -stop;
    ROS_INFO("时刻相减:%.2f",du2.toSec());

    //持续时间与持续时间的运算
    ros::Duration du3 = du1 + du2;
    ros::Duration du4 = du1 - du2;
    ROS_INFO("du1 + du2 = %.2f",du3.toSec());
    ROS_INFO("du1 - du2 = %.2f",du4.toSec());

    //-------------------------------------------------------------------
    ROS_INFO("------------------------定时器---------------------------");
    /*
    ros::Timer = nh.createTimer(ros::Duration period,  //时间间隔 --- 1s
                const ros::TimerCallback &callback,    //回调函数 ---- 封装业务
                bool oneshot = false,                  //是否一次性 默认false
                bool autostart = true)                 //是否自动启动 默认true
    */
    ros::Timer timer = nh.createTimer(ros::Duration(1),cb);  //参数:时间间隔,回调函数
    ros::spin();// 需要回旋
    return 0;
}

输出:
注:
“持续时间"那里会停顿5秒;定时器会以1s的频率输出”--------------"
定时器:ros::Timer timer = nh.createTimer(ros::Duration(1),cb,false,true)
将第四个参数改为true时,需要后面加上:

timer.start();  //手动启动

在这里插入图片描述
补充:在上述例子中回调函数那里改为:

    void cb(const ros::TimerEvent& event){
        ROS_INFO("----------------------");
        ROS_INFO("函数被调用的时刻:%.2f",event.current_real.toSec());
    }

则输出:
在这里插入图片描述

5. 其他函数

5.1 节点关闭:

在发布实现时,一般会循环发布消息,循环的判断条件一般由节点状态来控制,C++中可以通过 ros::ok() 来判断节点状态是否正常,而 python 中则通过 rospy.is_shutdown() 来实现判断,导致节点退出的原因主要有如下几种:

  1. 节点接收到了关闭信息,比如常用的 ctrl + c 快捷键就是关闭节点的信号;
  2. 同名节点启动,导致现有节点退出;
  3. 程序中的其他部分调用了节点关闭相关的API (C++中是ros::shutdown(),python中是rospy.signal_shutdown())

例:(执行50次结束循环)

if (count >= 50)
{
	ros::shutdown();
}

5.2 日志相关:

  1. DEBUG(调试): 只在调试时使用,此类消息不会输出到控制台;
  2. INFO(信息): 标准消息,一般用于说明系统内正在执行的操作;
  3. WARN(警告): 提醒一些异常情况,但程序仍然可以执行;
  4. ERROR(错误): 提示错误信息,此类错误会影响程序运行;
  5. FATAL(严重错误): 此类错误将阻止节点继续运行。
#include "ros/ros.h"
/*
    ROS中的日志:
        演示不同级别日志的基本使用
*/
int main(int argc, char *argv[])
{
    setlocale(LC_ALL,"");
    ros::init(argc,argv,"hello_log");
    ros::NodeHandle nh;

    //日志输出
    ROS_DEBUG("调试信息"); //不会打印在控制台
    ROS_INFO("一般信息");
    ROS_WARN("警告信息");  //输出为黄色
    ROS_ERROR("错误信息"); //输出为红色
    ROS_FATAL("严重错误"); //输出为红色
    
    return 0;
}

输出:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值