ROS (二) ---- roscpp

roscpp

初始化函数

ros::init() 是节点中第一个调用的函数,参考。一般是将 argcargv 还有这个节点的名字传入。

Handler

ros::Handler 类。关于消息,服务在第一篇中已经说过。

Timer

创建定时器,每隔一段时间会自动调用函数。感觉像是 ROS 里面自带的多线程。

比如写传感器节点时,希望传感器每隔一段时间发布传感器信息,就可以用定时器。

补充:ROS Time

ROS 中有两种时间,ROS TimeWall TimeROS Time 指 ROS 网格中的时间。在非仿真环境下和 Wall Time 相同,就是当前时间。但是在仿真环境,或者数据包回放时,这个时间可以被修改(加速,减速),但是 Wall Time 不行。

两种时间类型。Time 指时刻,Duration 指时间间隔。

ros::Time cur = ros::Time::now(); // get current time

注意时间!!在 Rosbag 中有两个时间戳,外层的是记录这个数据包时候的时间,数据里面 header 才是真正数据发布的时间,不要弄混了。

定时器创建

传入的函数有三种类型,见此处。创建的完整示例见此处

CallbackQueue

回调队列,用于管理和响应 ROS 回调函数。

补充 ros spinning

ROS 将线程模型隐藏,通过 spin 机制调用。单线程 spin:

// one way
ros::init(argc, argv, "my_node");
ros::NodeHandle nh;
ros::Subscriber sub = nh.subscribe(...);

ros::spin();

// 设置调用频率 -- 10Hz
ros::Rate r(10); // 10 hz
while (should_continue)
{
	// do some work, publish some messages, etc. ...
    ros::spinOnce();
    r.sleep();
}

// Use default callback queue
#include <ros/callback_queue.h>
ros::NodeHandle n;
while (ros::ok())
{
	// call one the functions with timeout 0.1
	ros::getGlobalCallbackQueue()->callAvailable(ros::WallDuration(0.1));
}

Usage

  • 配置

也可以自己定义 Callback Queue 将不同速率的任务放在不同队列中,实现速度匹配。配置时,可以在各个 subscire 等函数的 Option 中指定 CallbackQueue。或者是直接用 NodeHandle, 将同一 NodeHandle 下所有消息,服务都指定为一个 CallbackQueue

ros::NodeHandle nh;
nh.setCallbackQueue(&my_callback_queue);

// 使用 for 循环处理回调函数队列
while (ros::ok())
{
	// call one the functions with timeout 0.1
	my_callback_queue.callAvailable(ros::WallDuration());
}

// 使用 Spinner 处理回调函数队列(Spinner 见下文)
ros::AsyncSpinner spinner(0, &my_callback_queue);
spinner.start();

ros::MultiThreadedSpinner spinner(0);
spinner.spin(&my_callback_queue);
  • Manually call

CallbackQueue 有两种方式调用队列中的等待函数。

  1. callAvailable() 调用队列中所有的等待函数。
  2. callOne() 调用当前队列中等待时间最长的函数。

传入参数 Timeout 是空队列等待新的回调函数的时限。

MultiThreadedSpinner & AsyncSpinner

推荐使用 AsyncSpinner

  • ros::MultiThreadedSpinner

ros::MultiThreadedSpinner 是阻塞式的。如果创建时不显示声明,会创建与 CPU 核数相同的线程数。

ros::MultiThreadedSpinner spinner(4); // Use 4 threads
spinner.spin(); // spin() will not return until the node has been shutdown
  • ros::AsyncSpinner

ros::AsyncSpinner 是非阻塞式的。Instead of a blocking spin() call, it has start() and stop() calls, and will automatically stop when it is destroyed. (or stop() / ros::shutdown() is called) Please note that the ros::waitForShutdown() function does not spin on its own, so the example above will spin with 4 threads in total.

ros::AsyncSpinner spinner(4); // Use 4 threads
spinner.start();
ros::waitForShutdown();

Logging

日志文件位置:Everything enabled goes into the log file. Your node’s log file will be in ~/.ros/log unless you override it with the ROS_HOME or ROS_LOG_DIR environment variables.

使用 rqt_console 实时查看日志信息。

设置等级

总共有五等:DEBUG, LOG, WARN, ERROR, FATAL,命名规则是ROS_<verbosity level>[_STREAM][_<other>]

Logging Output

  • stdout

DEBUG and INFO messages arrive on stdout if they are enabled. Note that this may not be sent to the screen depending on the value of the roslaunch/XML/node output parameter.

指 launch 文件中 output = "screen | log"

  • stderr

WARN, ERROR and FATAL messages arrive on stderr if they are enabled.

Setting Verbosity Levels

  1. through a configuration file which sets the verbosity level for every node in the system.
  2. the second is at runtime through the rqt_logger_level (former rxloggerlevel) or rqt_console (former rxconsole) tools.
  3. the third is programmatically through the rosconsole API (*)
#include <ros/console.h>
if( ros::console::set_logger_level(ROSCONSOLE_DEFAULT_NAME, ros::console::levels::Debug) ) {
   ros::console::notifyLoggerLevelsChanged();
}

命名空间

ROS 中元素(Node, Parameters, Topics, Services)都有自己的名字,这就需要一个统一的管理方式 – 命名空间。ROS 的命名方式和 Linux 文件管理相似。命名默认使用相对路径,这样即使变量名相同,两个包可以分别调用各自变量而无需担心冲突。

  • relative 命名

对于在 /wg 下的节点 node1,如果使用"node2"则根据相对路径解析到/wg/node2

  • global 命名,同 Linux

  • private 命名

对于在 /wg 下的节点 node1,如果使用 "~/param1" 则解析到 /wg/node1/param1

Remapping

remap 应用于如下场景:比如在迁移一个 CV 软件包时,里面接受图片是用的 camera 话题,但实际图片由相机发布在 "/kinetic/left/color"。如果不想更改代码,可以使用 remap 方法,将

<remap from="/kinetic/left/color" to="camera"/>

remapping 规则见 link

参数服务器(Parameter Server)

运行机器人节点时传入参数:相机的内参,雷达的有效距离。ROS 使用参数服务器管理参数。可以通过 roslaunch 在启动时设置参数,也可以通过程序在运行时动态设置

Get Param

推荐使用 nh.getParam() 函数读取,nh.setParam() 设置。


版权声明:本文为lib0000原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。