目录
在一些需要可视化的任务重,我们通常会借助ROS里的Rviz来进行,比如自动驾驶调试的车辆显示。本篇以一个简单的例子,介绍如何使用ROS在Rviz中进行显示。
1. 事例代码
先看完整代码:
#include "ros/ros.h"
#include "visualization_msgs/Marker.h"
void set_property(visualization_msgs::Marker& cricle){
cricle.header.frame_id = "frame"; // 设置帧id
cricle.header.stamp = ros::Time();
// id和命名空间关联起来,形成唯一的id,用于将各个标志物区分开来
cricle.ns = "circle1";
cricle.id = 0;
cricle.action = visualization_msgs::Marker::ADD;
cricle.type = visualization_msgs::Marker::SPHERE;
//设置物体中心的坐标
cricle.pose.position.x = 0;
cricle.pose.position.y = 0;
cricle.pose.position.z = 0;
//设置物体在各个方向上的尺寸
cricle.scale.x = 1.0; //m
cricle.scale.y = 1.0;
cricle.scale.z = 1.0;
//设置颜色及透明度(cricle.color.a 是透明度)
cricle.color.a = 1.0;
// cricle.color.r = 1.0;
// cricle.color.g = 1.0;
cricle.color.b = 1.0;
//标志物显示持续的时间
cricle.lifetime = ros::Duration();
}
int main(int argc, char **argv){
ros::init(argc, argv, "rviz_test");
ros::NodeHandle n; // 管理节点操作和通信的对象,荣国nodehandle可以对节点进行各类操作
// 创建了一个消息发布者功能,要发布的消息类型为visualization_msgs::Marker,消息topic为"topic"
ros::Publisher marker_pub = n.advertise<visualization_msgs::Marker>("topic", 10);
// 设置要发送的内容
visualization_msgs::Marker cricle;
set_property(cricle);
// 因为就发送了一次消息,防止连接还未完全建立好错过消息,先等待一会儿
while (marker_pub.getNumSubscribers() < 1) {
sleep(1);
}
// 通过消息发布者把设置好的内容发送出去
marker_pub.publish(cricle);
// 进入循环监听消息
ros::spin();
return 0;
}
2. 发送框架及内容分析
先关注main函数的部分,想要在rviz中显示,需要四个基本步骤:
- ros::init(argc, argv, "rviz_test") 创建节点
- ros::NodeHandle n 创建对节点的管理
- ros::Publisher marker_pub 创建发布给rviz的消息发布者
- marker_pub.publish() 把消息发布出去
有了上面的基本框架,就可以填充消息内容了,在第三步创建消息发布者时,对消息的类型和使用的话题进行了定义,定义类型为visualization_msgs::Marker,消息topic为"topic"。Marker类型对定义具体的消息内容很重要,topic对在rviz中的显示设置很重要。
ros::Publisher marker_pub = n.advertise<visualization_msgs::Marker>("topic", 10);
在定义好了以上之后,就可以设置具体的发送内容了:
visualization_msgs::Marker cricle;
set_property(cricle);
具体对于circle内容的定义,见set_property()内部,一些中心点坐标,尺寸,颜色透明度等信息当然大都是需要的。其中比较重要的是:
- header.frame_id的设置,虽然说是帧id,其实可以理解为每一帧的相对坐标系,在rviz里面对应的是global options里的fixed frame。
- ns和id的设置,是对应frame_id下的各个物体在一个命名空间里的id是唯一的,用来区分每个物体
- lifetime的设置,设置物体显示的时间,这里为了演示方便设置的是持续显示
3. rviz中显示效果及设置
上面的代码画了一个蓝色球体,我们打开rviz,注意global options下的fixed frame和Marker下的Marker Topic和代码中的名称一致,就可以显示了,在Namespaces下,还可以看到我们定义的命名空间circle1,显示的蓝色球体的id就是0。
4. 关于ros信号建立先后的补充
另外,关于下面这行代码单独说明。
while (marker_pub.getNumSubscribers() < 1) {
sleep(1);
}
如果不加,有可能会在rviz中无法显示。是因为我们为了演示实际上只发送了一次包含圆球内容的信息,而这个时候如果rviz作为接收者还没有建立好,就可能会错过这条消息。所以这句话是表示在接收者准备好后,在执行后面的发送操作。