第八篇:ROS的rviz三维可视化平台_rviz python slam可视化-程序员宅基地

技术标签: ROS系统平台开发  自动驾驶  r语言  开发语言  

系列文章目录

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
TODO:写完再整理


前言

认知有限,望大家多多包涵,有什么问题也希望能够与大家多交流,共同成长!

本文先对rviz三维可视化平台做个简单的介绍,具体内容后续再更,其他模块可以参考去我其他文章


提示:以下是本篇文章正文内容

一、功能

rviz是三维可视化工具,强调把已有的数据可视化显示,用于直观的显示数据。(机器人模型、坐标、运动规划,导航、点云、图像、SLAM)。rviz提供了很多插件,这些插件可以显示图像、模型、路径等信息,但是前提都是这些数据已经以话题、参数的形式发布,rviz做的事情就是订阅这些数据,并完成可视化的渲染,rviz帮助开发者实现所有可监测信息的图形化显示,开发者也可以在rviz的控制界面下,通过rviz的planning插件的功能,根据按钮、滑动条、数值等方式,控制机器人的行为【防盗标记–盒子君hzj】

.
.

二、安装并运行rviz

1.安装rviz

rviz已经集成在桌面完整版的ROS系统当中,如果已经成功安装了桌面完整版的ROS,【防盗标记–盒子君hzj】可以直接跳过这一步骤,否则,请使用如下命令进行安装:

$ sudo apt-get install ros-kinetic-rviz

2.运行rviz

$ roscore
$ rosrun rviz rviz

.
.

三、界面介绍

0 :3D视图区,用于可视化显示数据,目前没有任何数据,所以显示黑色
1 :工具栏,提供视角控制、目标设置、发布地点等工具
2 :显示项列表,用于显示当前选择的显示插件,可以配置每个插件的属性
3 :视角设置区,可以选择多种观测视角
4 :时间显示区,显示当前的系统时间和ROS时间
.
.

四、数据可视化原理及步骤

1.原理

行数据可视化的前提当然是要有数据,假设需要可视化的数据以对应的消息类型发布,我们在rviz中使用相应的插件订阅该消息即可实现显示
可视化显示都是通过消息的订阅来完成的,机器人通过ROS发布数据,rviz订阅消息接收数据,然后显示【防盗标记–盒子君hzj】

2.步骤

(1)在源代码中按照可视化话题类型,发布话题

(1)根据消息类型visualization_msgs编程
具体怎么操作可以去wiki上面查,掌握编程的套路,(编程根据数据接口和api会填入数据就行)
【常用的可视化类型记住一下,不常用的上wiki查】


(2)在程序上编程实现了可视化api后,在rviz界面上才可以进行勾选订阅和改变参数的

【DisplayTypes】显示元素的类型
写在了另外一个博客~

(2)rviz订阅对应话题步骤

(1)Add添加显示插件
		方法一:通过显示的类型添加(By display type)
		方法二:通过话题添加(By topic)【常用 】,它会自动识别系统中发布的话题【防盗标记–盒子君hzj】
		方法三:知道话题名字,输入进行搜索


(2)配置话题显示插件
	添加完成后,rviz左侧的Dispaly中会列出已经添加的显示插件;点击插件列表前的加号,
	可以打开一个属性列表(这些属性列表设置也是编程里面visualizatian_msgs接口的成员)
	【可视化颜色、大小等等可以再程序里面改也可以再display中进行配置】,根据需求设置属性。
	一般情况下,“Topic”属性较为重要,用来声明该显示插件所订阅的数据来源,如果订阅成功,在中间的显示区应该会出现可视化后的数据。

(3)保存当前配置好的RVIZ环境

方法:File->Save Config As,下次直接打开这个.rviz就可以直接显示了

3.注意

如果显示有问题,请检查属性区域的“Status”状态。Status有四种状态:OK、Warning、Error和Disabled,【防盗标记–盒子君hzj】
如果显示的状态不是OK,那么请查看错误信息,并详细检查数据发布是否正常

编程时要清除ros可视化,每次显示才会正常

五、插件扩展机制

(1)默认插件(rviz提供)

【用好默认插件已经可以了-我们通常用的就是默认插件的数据类型】

(1)订阅话题的插件
包含坐标轴、摄像头图像、地图、激光等数据。


(2)发布话题的插件
	(1)rviz中的Nav_3D的目标点(goal),在程序中是怎么被接收的?
	【在目标点订阅函数的话题名中被订阅,在回调函数中对这个话题的目标值变量进行处理】
	【话题名可以使用rviz中默认的话题名,也可以自己写一个rviz的插件自己进行定义,rviz和gazebo都是支持插件的】
	
	(2)rviz最上面的界面栏可以发布话题,通过“+”“-”符号添加或者删除话题,【防盗标记–盒子君hzj】
	
	发布的话题名字可以通过rostopic list查看,若是要修改可以在.rviz中进行修改

(2)扩展插件

ROS的rviz仿真插件的编写,可以按照rviz提供的topic type的规范来写

作为一个平台,rviz可以显示的数据不仅仅如此。rviz支持插件扩展机制。如果需要添加其他数据的显示,也可以通过编写扩展插件的形式进行添加

jsk的rviz插件查一查怎么用?

planning有什么插件?【防盗标记–盒子君hzj】

(3)rviz的人机调试界面开发

可视化界面编程–QT(Qt中的重要概念——信号、槽,类似于回调函数)

整体原理
读取用户的输入,然后转换成ROS的topic

举例

//rviz_plugin_for_command.cpp
namespace test_rviz_plugin{
    
    TestRvizPlugin::TestRvizPlugin(QWidget *parent):Panel(parent)
    {
    
    	//创建按钮
        auto *button_layout = new QHBoxLayout;

        boundary_record_button_ = new QPushButton("Record Boundary",this);
        button_layout->addWidget(boundary_record_button_);

        connected_record_button_ = new QPushButton("Record Connected Road",this);
        button_layout->addWidget(connected_record_button_);

        virtualwall_record_button_ = new QPushButton("Record Virtual Wall",this);
        button_layout->addWidget(virtualwall_record_button_);

        start_task_button_ = new QPushButton("Start Task", this);
        button_layout->addWidget(start_task_button_);

        start_unFinish_task_button_ =
            new QPushButton("Start unFinish Task", this);
        button_layout->addWidget(start_unFinish_task_button_);

        start_go_charge_button_ = new QPushButton("Start go charge Task", this);
        button_layout->addWidget(start_go_charge_button_);

        pause_task_button_ = new QPushButton("Pause Task", this);
        button_layout->addWidget(pause_task_button_);

        resume_task_button_ = new QPushButton("resume Task", this);
        button_layout->addWidget(resume_task_button_);

        leave_dock = new QPushButton("leave dock", this);
        button_layout->addWidget(leave_dock);

        end_task_button_ = new QPushButton("end Task", this);
        button_layout->addWidget(end_task_button_);

        setLayout(button_layout);

        // 信号连接---点击信号发生,连接到槽函数callback
        connect(boundary_record_button_, SIGNAL(clicked()), this,
                SLOT(boundaryRecordCallback()));
        connect(connected_record_button_, SIGNAL(clicked()), this,
                SLOT(connectedRoadRecordCallback()));
        connect(virtualwall_record_button_, SIGNAL(clicked()), this,
                SLOT(virtualwallRcordCallback()));

        connect(start_task_button_, SIGNAL(clicked()), this,
                SLOT(startTaskCallback()));

        connect(start_unFinish_task_button_, SIGNAL(clicked()), this,
                SLOT(startUnFinishTaskCallback()));

        connect(start_go_charge_button_, SIGNAL(clicked()), this,
                SLOT(startGoChargeCallback()));

        connect(pause_task_button_, SIGNAL(clicked()), this,
                SLOT(PauseTaskCallback()));

        connect(resume_task_button_, SIGNAL(clicked()), this,
                SLOT(ResumeTaskCallback()));

        connect(leave_dock, SIGNAL(clicked()), this, SLOT(LeaveDockCallback()));

        connect(end_task_button_, SIGNAL(clicked()), this,
                SLOT(EndTaskCallback()));

        boundary_record_pub =
            nh_.advertise<std_msgs::Bool>("record_boundary_button", 10);
        connected_road_record_pub =
            nh_.advertise<std_msgs::Bool>("record_connected_road_button", 10);
        virtualwall_record_pub =
            nh_.advertise<std_msgs::Bool>("record_virtualwall_button", 10);

        start_task_pub = nh_.advertise<std_msgs::Bool>("start_task_button", 10);
        start_unFinish_task_pub =
            nh_.advertise<std_msgs::Bool>("start_unFinish_task_button_", 10);
        start_go_charge_pub =
            nh_.advertise<std_msgs::Bool>("start_go_charge_button_", 10);
        pause_task_pub =
            nh_.advertise<std_msgs::Bool>("pause_task_button_", 10);
        resume_task_pub =
            nh_.advertise<std_msgs::Bool>("resume_task_button_", 10);
        leave_dock_pub =
            nh_.advertise<std_msgs::Bool>("leave_dock_button_", 10);
        end_task_pub = nh_.advertise<std_msgs::Bool>("end_task_button_", 10);

        is_start_record_boundary.data = false;
        is_start_record_connected_road.data = false;
        is_start_record_virtualwall.data = false;

        // start_task.data = false;
        // start_unFinish_task.data = false;
        // start_go_charge.data = false;
        // pause_task.data = false;
        // resume_task.data = false;
        // leave_dock_task.data = false;
        // end_task.data = false;
    }

    // 加载配置数据---必须要有的
    void TestRvizPlugin::load(const rviz::Config &config) {
    
        Panel::load(config);
    }

    // 将所有配置数据保存到给定的Config对象中。在这里,重要的是要对父类调用save(),以便保存类id和面板名称。---必须要有的
    void TestRvizPlugin::save(rviz::Config config) const {
    
        Panel::save(config);
    }

    void TestRvizPlugin::boundaryRecordCallback() {
    
        if (!is_start_record_boundary.data)
            is_start_record_boundary.data = true;
        else
            is_start_record_boundary.data = false;
        ROS_INFO("Record Boundary");
        boundary_record_pub.publish(is_start_record_boundary);
    }
}
//rviz_plugin_for_command.h
#ifndef RVIZ_PLUGIN_FOR_COMMAND_H
#define RVIZ_PLUGIN_FOR_COMMAND_H
#include <ros/ros.h>
#include <rviz/panel.h>  //plugin基类的头文件
#include <std_msgs/Bool.h>

#include <QHBoxLayout>
#include <QPushButton>
#include <QString>
namespace test_rviz_plugin{
    
class TestRvizPlugin : public rviz::Panel {
    
    // 所有的plugin都必须是rviz::Panel的子类
    // 后边需要用到Qt的信号和槽,都是QObject的子类,所以需要声明Q_OBJECT宏
    Q_OBJECT

   public:
    // 构造函数,在类中会用到QWidget的实例来实现GUI界面,这里先初始化为0即可
    TestRvizPlugin(QWidget *parent = 0);

    // 重载rviz::Panel基类中的函数,用于保存、加载配置文件中的数据
    virtual void load(const rviz::Config &config);
    virtual void save(rviz::Config config) const;

    // 回调函数
   protected Q_SLOTS:
    void boundaryRecordCallback();
    void connectedRoadRecordCallback();
    void virtualwallRcordCallback();
    void startTaskCallback();

    void startUnFinishTaskCallback();
    void startGoChargeCallback();
    void PauseTaskCallback();
    void ResumeTaskCallback();
    void LeaveDockCallback();
    void EndTaskCallback();

   private:
    ros::NodeHandle nh_;
    QPushButton *boundary_record_button_;
    QPushButton *connected_record_button_;
    QPushButton *virtualwall_record_button_;

    QPushButton *start_task_button_;
    QPushButton *start_unFinish_task_button_;
    QPushButton *start_go_charge_button_;
    QPushButton *pause_task_button_;
    QPushButton *resume_task_button_;
    QPushButton *leave_dock;
    QPushButton *end_task_button_;

    std_msgs::Bool is_start_record_boundary;
    std_msgs::Bool is_start_record_connected_road;
    std_msgs::Bool is_start_record_virtualwall;

    // std_msgs::Bool start_task;
    // std_msgs::Bool start_unFinish_task;
    // std_msgs::Bool start_go_charge;
    // std_msgs::Bool pause_task;
    // std_msgs::Bool resume_task;
    // std_msgs::Bool leave_dock_task;
    // std_msgs::Bool end_task;

    ros::Publisher boundary_record_pub;
    ros::Publisher connected_road_record_pub;
    ros::Publisher virtualwall_record_pub;

    ros::Publisher start_task_pub;
    ros::Publisher start_unFinish_task_pub;
    ros::Publisher start_go_charge_pub;
    ros::Publisher pause_task_pub;
    ros::Publisher resume_task_pub;
    ros::Publisher leave_dock_pub;
    ros::Publisher end_task_pub;
};
}
#endif 

效果如下
在这里插入图片描述

参考链接
https://zhuanlan.zhihu.com/p/39390512


总结

启动rviz之前要先启动roscore,遇到错误或者警告先看提示

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_35635374/article/details/121248149

智能推荐

AQS 源码流程分析_aqs 入对之后就一定顺序执行-程序员宅基地

文章浏览阅读455次。我们日常开发中,经常会碰到并发的场景,在 Java 中语言体系里,我们会想到 ReentrantLock、CountDownLatch、Semaphore 等工具,但你是否清楚它们内部的实现原理?这些工具都很类似,底层都是基于AbstractQueuedSynchronizer(AQS)来实现的。今天我们就来一起学习 AQS 内部原理。_aqs 入对之后就一定顺序执行

C语言--编写程序,绘制菱形图_c语言画菱形-程序员宅基地

文章浏览阅读4.1k次。编写一个程序,在屏幕上显示如下图形(图形的层数有输入者自行定义)源代码如下所示:#include<stdio.h>int main(){ int line; // 菱形总行数 int column; // 菱形总列数 int i; // 当前行 int j; // 当前列 printf("请输入菱形的行数(奇数):"); scanf("%d", &line); while(2) { if(line%_c语言画菱形

怎么实现跨域?配置vue跨域proxy,jsonp跨域很简单-程序员宅基地

文章浏览阅读760次,点赞10次,收藏28次。/ 封装axios请求的模块// 用axios重新生成了请求的实例baseURL: ‘’, // 项目发送axios请求的公共地址 值为空timeout: 5000 // 请求超时时间 这里是请求超过五秒后还没有获得请求结果 提示请求超时})// config包含了请求相关的所有信息// 可以同过config对象给请求配置或者修改信息return config // 将配置完成的token返回 如果不返回 请求不会继续进行// 请求发生错误时的回调函数。

兼容Office和WPS中Word图标库_wps officeimageid-程序员宅基地

文章浏览阅读108次。最近在用c#写VSTO文字操作插件,因为要同时在WPS中有效,因此进行了提取。_wps officeimageid

Kali Linux 解决Wine下中文或英文字体乱码的问题 ,一劳永逸法 。_kali wine 中文方块-程序员宅基地

文章浏览阅读4k次,点赞11次,收藏14次。  解决 Kali Linux中 Wine下英文方块乱码的方法  最近在wine下使用notepad++和sublime编辑器的时候,发现英文全部均是方块乱码,熟悉wine的朋友们一定会记得,在.wine文件夹下模拟器的文件结构是和Windows是非常相似的: nautilus .wine/drive_c/  wine中文件结构:  Windows下文件结构:  如果,我们分别在Linux终端下对.wine/drive_c和在Powershell终端对C盘进行tree查看,就会发现文件是高_kali wine 中文方块

Vue.js的双向绑定原理-程序员宅基地

文章浏览阅读285次。vue3双向绑定原理

随便推点

Java 常用类 03 可变字符串和BigDecimal(BigInteger)_java字符串和bigdecimal类-程序员宅基地

文章浏览阅读335次。3.1 可变字符串和BigDecimal3.1.1 可变字符串由于我们的字符串,是不可变的。每次都要在 字符串池里 新建和共享。这样效率很低,而且占用空间大。我们的 Java 就开发了 可变字符串下面的两者,都比传统的 String 类型要快很多。① StringBuffer:JDK1.0提供的,效率低,线程安全。它是实现开辟一个缓冲区,然后操作的时候,直接在 缓冲区里进行操作。② StringBuilder:JDK5.0提供的,效率高,线程不安全3.1.2 StringBuffer①_java字符串和bigdecimal类

【基于FPGA的芯片设计】32×32位寄存器堆_fpga2s需要多少位寄存器-程序员宅基地

文章浏览阅读2.6k次,点赞9次,收藏2次。32×32位寄存器堆设计,杭电计算机组成原理实验四,实验的开发工具是vivado2018,vivado2022也兼容2018_fpga2s需要多少位寄存器

STM32F103 软件实现随机数_stm32f103c8t6可以生成随机数么-程序员宅基地

文章浏览阅读644次。因为STM32F103C8T6,没有硬件随机数,所以需要自己通过软件配置。最后得到的mmm1变量为一个0~100的随机值。首先增加一段include用于产生真随机数。_stm32f103c8t6可以生成随机数么

微信h5页面打开微信内置地图及wx.openLocation回调成功调不起页面的问题_h5 wx.openlocation-程序员宅基地

文章浏览阅读4.5k次。先说下需求吧,我们的需求是通过一个经纬度,然后打开微信内置的地图页面代码如下://导航到停车场 gogogo() { //获取当前页面url //var url = location.href.split('#')[0]; // alert(11111) // window.location.href = // "https://apis.map.qq.com/uri/v1/marker?marker=coord:30.595810_h5 wx.openlocation

Linux——部署DNS服务二: 正向解析,反向解析,双向解析_用于减少域名到ip地址的映射的技术是-程序员宅基地

文章浏览阅读616次。一、DNS正向解析(权威配置) 作用: 用于域名到IP地址的映射,当DNS客户端请求解析某个域名时,DNS服务器通过正向查找,并返回给DNS客户端对应的IP地址 正向解析的部署:删除forwarders { 114.114.114.114; };(或者注释掉)vim /etc/named.rfc1912.zones新添加一个zone(可以复制19到23行,粘贴在底下再进行修改..._用于减少域名到ip地址的映射的技术是

学习使用idea搭建SSH框架,并实现一个简单的登录功能_intellij idea ssh 登录系统教程-程序员宅基地

文章浏览阅读2.2k次。学习利用Struts2,Spring,Hibernate这三个框架来搭建项目的主体架构,实现简单的一个登录注册功能_intellij idea ssh 登录系统教程

推荐文章

热门文章

相关标签