利用ROS做机器人手眼标定和Qt+rviz+图片话题显示的UI设计

前言:

        博主是在上一篇博文的基础上作的研究和总结,希望这篇文章可以对诸君有用,同时博主也对鱼香ROS、小鱼大佬、以及其他相关创作者的支持表示由衷的感谢,本文章内容也将继续公开且代码开源。

        文章将讲述usb_cam(usb相机内参标定)、handeye-calib(手眼标定)、aruco_ros(AR码的追踪和位姿检测)的下载、编译以及使用和配置、librviz在Qt中的配置和使用以及图片话题的显示。

        可以参考手眼标定和AR码的追踪和位姿检测。

正文:

板块一:手眼标定

一、使用usb_cam来进行usb相机内参标定

        下载usb_cam:

# 下载对应版本 我这里是noetic版本
sudo apt-get install ros-noetic-usb-cam

        运行:

        1、修改参数

roscd usb_cam/
sudo gedit launch/usb_cam-test.launch
<launch>
  <node name="usb_cam" pkg="usb_cam" type="usb_cam_node" output="screen" >
    <!-- 相机驱动设备位置用ls /dev/video* 查看 -->
    <param name="video_device" value="/dev/video0" />
    <!-- 图片的宽度和高度 这个看相机参数了 -->
    <param name="image_width" value="1280" />
    <param name="image_height" value="720" />

    <param name="pixel_format" value="yuyv" />
    <param name="color_format" value="yuv422p" />

<!-- 相机的tf名称,最好默认 影响最后的图片话题 -->
    <param name="camera_frame_id" value="usb_cam" />
    <param name="io_method" value="mmap"/>

<!-- 内参标定结果文件保存位置 -->
    <param name="camera_info_url" type="string" value="file:///home/dev/.ros/camera_info/head_camera.yaml"/>
  </node>
<!-- 显示图片节点 -->
  <node name="image_view" pkg="image_view" type="image_view" respawn="false" output="screen">
    <remap from="image" to="/usb_cam/image_raw"/>
    <param name="autosize" value="true" />
  </node>
</launch>

        2、下载标定板

        进入Camera Calibration Pattern Generator – calib.io

70bc5420bfad4521ab3ee068b7e7c9e0.png

        3、开始标定

# 开启相机流
roslaunch usb_cam usb_cam-test.launch
# 新开终端运行内参标定程序 size 为网格角点数 square 是格子边长数 (参数就是上面图片中的说明)
rosrun camera_calibration cameracalibrator.py --size 11x15 --square 0.015 image:=/usb_cam/image_raw camera:=/usb_cam

caff061e74674b0b87a500de50234ae5.png

        注意:

        这里标定内参的结果会存在你usb_cam-test.launch文件中的位置,这个位置很重要,他是后面ArUco使用时用usb_cam来启动相机的参数之一。

二、handeye-calib(手眼标定)的下载、编译和使用

说明:

       1、 该源码内容由小鱼大佬提供,所以吃水不忘挖井人,感谢。

       2、该源码编译环境为安装好了ROS且最好没有Anaconda等虚拟环境的干扰(至少博主就是因为安装了Anaconda的开发环境导致python的版本不对,最后导致编译不通过和运行错误等问题)。

       3、该功能包编译是有几个依赖文件需要下载和安装。

下载和编译:

        1、创建工作目录并进入开始下载源码。

mkdir ~/hand_eye
cd ~/hand_eye
git clone https://gitee.com/ohhuo/handeye-calib.git

       2、编译源码

cd handeye-calib/
catkin_make

        注意:

        如果编译报错且提示是因为缺少包,那么你需要下载安装就好啦。一般就缺失transforms3d和tabulate两个包,安装就好了,如果还不行就缺啥安啥方法一样。

pip install transforms3d
pip install tabulate

        如果有其他一些关于pip的问题,可以看下面:

# pip安装过慢,可以尝试换清华源
 # 临时使用:
 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple 包名
 # 设为默认:
 pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

# 没有pip的话可以安装
 sudo apt-get install pip

  学习并使用:

        该内容将以功能包中README.md文件教程为主。

        1、准备工作:

        当我们在用到一个新的功能包或库时可以先阅读它的readme文件,当然小鱼大佬也提供了这么一个文件—–README.md,不过用记事本打开的话不怎么好看,所以我推荐安装一个Markdown编辑器,我这里有一个我总结好的离线安装版本Typora。

链接 提取码: xs66,下载完成后:直接下面命令,就安装好Typora了。

sudo bash install.sh

把功能包的README.md拖入Typora就可以阅读查看了。那么,你可以详细阅读README.md文件来学习和了解使用这个功能包。

        2、开始使用(README.md文件中的基础标定): 

        快读体验(眼在手上为例子)

        使用小鱼提供好的数据,可以快速体验手眼标定。

        参数配置

        找到程序中的src/handeye-calib/launch/base/base_hand_on_eye_calib.launch文件,文件中有两个可配置参数

  • base_handeye_data参数为从位姿文件所在的目录,默认config/base_hand_on_eye_test_data.csv

  • base_handeye_result 参数为结果存储文件目录,默认为config/result/base_hand_on_eye_result.txt

<launch>
    <!-- 需要输入两个参数 -->
    <arg   name="base_handeye_data"   default="$(find handeye-calib)/config/base_hand_on_eye_test_data.csv" />
    <arg   name="base_handeye_result"   default="$(find handeye-calib)/config/result/base_hand_on_eye_result.txt" />
​
    <node pkg="handeye-calib" type="base_hand_on_eye_calib.py" name="base_hand_on_eye_calib" output="screen" >
         <param name="base_handeye_data" value="$(arg base_handeye_data)" />
         <param name="base_handeye_result" value="$(arg base_handeye_result)" />
    </node>
</launch>

        运行程序

source devel/setup.bash
roslaunch handeye-calib base_hand_on_eye_calib.launch

        查看结果

程序会根据配置文件中的坐标进行计算,最终输出如下数据。数据包含不同算法下计算结果,以及计算结果的标准差和方差等数据。

眼在手上最终结果应取:end_link->marker之间关系。

4ef11bfb3588478896eb5e74f75ac19b.png

        3、在线标定:

        在线标定即实时从话题读取姿态信息进行计算,会在 四、标定结果(转换矩阵)的获取中再次提到。

        输入内容:

        1、机械臂位姿:可以通过话题、tf、机械臂的SDK、moveit节点等获取。

        2、标定板位姿:可以通过ArUco工具(下文会讲到它的安装、配置和使用)获取。

        输出内容:

        通过启动不同的launch文件可以得到:(眼在手上)机械臂末端与相机之间的位姿关系或者(眼在手外)机械臂基座与相机之间的位姿态关系。

    三、ArUco的安装和使用

        该功能包一共有两种安装方式:二进制文件安装和源码安装。 

        下载和安装:

         1、二进制安装

# 版本名称为ros的版本 
  sudo apt-get install ros-版本名称-aruco*

        2、源码下载安装

cd ~/hand_eye/handeye-calib/src
# 注意noetic-devel是ros对应版本 需要更改
git clone -b noetic-devel  https://github.com/pal-robotics/aruco_ros
# 回到工作空间
cd ..
catkin_make

        至此,你就将ArUco就安装好了,不同的是一个(二进制安装)是在系统ROS环境下,一个(源码安装)在你建立的ROS环境(工作空间handeye-calib)下。

        参数说明:

        该部分内容,可以仿照aruco_ros(功能包)/aruco_ros/launch中的 single.launch文件来了解,但是我这里就结合小鱼的handeye-calib 功能包中的aruco_start_usb_cam.launch来说明,它的位置在 handeye-calib(功能包)/launch/aruco下,其中标定板的下载和打印,我会在下面说明。

<launch>
<!-- 相机内参标定文件位置 一般为file:///home/用户名/.ros/camera_info/head_camera.yaml -->
    <arg name="camera_info_url"  default="file:///home/ros/.ros/camera_info/head_camera.yaml"/>
<!-- usb相机参数 -->
    <!-- 相机驱动设备位置用ls /dev/video* 查看 -->
    <arg name="video_device"     default="/dev/video0"/>
    <!-- 图片宽度和高度 -->
    <arg name="image_width"      default="640"/>
    <arg name="image_height"     default="480"/>

<!-- 标定板参数 -->
    <!-- markerId: 标定板编号,就是你所用的标定板的id,可以通过`在线生成标定板:https://chev.me/arucogen/进行生成并打印 markerSize:标定板的宽度 单位m -->
    <arg name="markerId"        default="0"/>
    <arg name="markerSize"      default="0.107"/> 
<!-- 剩下的默认就好 -->   
    <arg name="eye"             default="left"/>
    <arg name="marker_frame"    default="aruco_marker_frame"/>
    <arg name="ref_frame"       default=""/>  
    <arg name="corner_refinement" default="LINES" />
 
<!-- 传入参数启动相机 -->
    <node name="usb_cam" pkg="usb_cam" type="usb_cam_node" output="screen" >
        <param name="camera_info_url" type="string" value="$(arg camera_info_url)"/>
        <param name="video_device" value="$(arg video_device)" />
        <param name="image_width" value="$(arg image_width)" />
        <param name="image_height" value="$(arg image_height)" />
        <param name="pixel_format" value="yuyv" />
        <param name="camera_frame_id" value="usb_cam" />
        <param name="io_method" value="mmap"/>
    </node>

<!-- 传入参数启动aruco_ros识别标定板位姿 -->
    <node pkg="aruco_ros" type="single" name="aruco_single">
        <remap from="/camera_info" to="/usb_cam/camera_info" />
        <remap from="/image" to="/usb_cam/image_raw" />
        <param name="image_is_rectified" value="True"/>
        <param name="marker_size"        value="$(arg markerSize)"/>
        <param name="marker_id"          value="$(arg markerId)"/>
        <param name="reference_frame"    value="$(arg ref_frame)"/> 
        <param name="camera_frame"       value="camera_frame"/>
        <param name="marker_frame"       value="$(arg marker_frame)" />
        <param name="corner_refinement"  value="$(arg corner_refinement)" />
    </node> 

<!-- 启动image_view显示识别结果 -->
    <node name="image_view" pkg="image_view" type="image_view" respawn="false" output="screen">
        <remap from="image" to="/aruco_single/result"/>
        <param name="autosize" value="true" />
    </node>


</launch>

        标定板下载和打印:

        下载网站:Online ArUco markers generator        c1efe7cc4de448a18e8ade3899a8e794.png     cd98bfe3672148479cc4541427bc67ed.png

        运行结果:

        当你把参数修改好后,可以开始运行一下。

roslaunch handeye-calib aruco_start_usb_cam.launch

就可以有这个结果辣

0d54846cca384278a3896352f65a9100.png

这个时候,你可以查看你的话题列表就可以找到该标定板的位姿话题(/aruco_single/pose),那么我们把他和handeye-calib功能包中需要的标定板位姿话题统一起来不就有一个输入了吗,至于另一个机器人位姿输入就需要各位仁兄根据自己的实际情况来设计和获取了。

1b15bb98639a4a52839e41c23175d48d.png

四、标定结果(转换矩阵)的获取

        说明:

        这一部分其实际上在 二、handeye-calib(手眼标定)的下载、编译和使用中有提到,其实阅读README.md文件,一步步来就OK了很详细的。

        运行:

        只要你把你的机器人位姿和handeye-calib中的话题和类型统一(建议先看下文参数,更改后再运行)。

# 眼在手
roslaunch handeye-calib online_hand_on_eye_calib.launch

# 眼到手
roslaunch handeye-calib online_hand_to_eye_calib.launch 

        变换机器人位置,以拍到并识别到AR码为准记录数据,多保记录几组后可以计算完成后就可保存。

r  rocord    记录一组手眼数据(当记录的数据大于程序计算所需的数据量之后会进行自动计算)
c  calculate 计算当前数据
s  save      保存数据
p  print     打印当前数据到屏幕上(格式为 type,x,y,z,rx,ry,rz 角度制)
q  quit      退出标定程序

        参数:

        其中,关于两个launch文件的参数说明:

<launch>
    <!-- ArUco获得的标定板位姿话题 类型 geometry_msgs::Pose-->
    <arg   name="camera_pose_topic"   default="/aruco_single/pose" />
    <!-- 机械臂位姿话题 类型 geometry_msgs::Pose-->
    <arg   name="arm_pose_topic"   default="/arm_pose" />

    <arg   name="base_link"   default="/base_link" />
    <arg   name="end_link"   default="/link7" />

    <node pkg="handeye-calib" type="online_hand_on_eye_calib.py" name="online_hand_on_eye_calib" output="screen" >
         <param name="arm_pose_topic" value="$(arg arm_pose_topic)" />
         <param name="camera_pose_topic" value="$(arg camera_pose_topic)" />
    </node>
    
    <node pkg="handeye-calib" type="tf_to_pose.py" name="tf_to_pose" output="screen" >
         <param name="arm_pose_topic" value="$(arg arm_pose_topic)" />
         <param name="base_link" value="$(arg base_link)" />
         <param name="end_link" value="$(arg end_link)" />
    </node>
    
</launch>

        运行结果:

        可参考基于ROS的手眼标定程序解决方案|支持眼在手外/上_ros手眼标定-CSDN博客

a5e4d7a1c3314e619ac6cc31ce848962.png

板块二:Qt上rviz+图片话题显示的UI设计

一、rviz的使用和介绍

        说明:

        1、该部分内容旨在学习和了解rviz的功能和基本操作方法,如果你对这个很熟悉,可以选择跳过。

          2、RViz(Robot Visualization)是一个用于可视化机器人系统的开源工具,用于显示和调试机器人的传感器数据、状态信息和运动规划等。它是ROS(Robot Operating System)的一部分,是ROS中最常用的可视化工具之一。RViz提供了丰富的功能和可定制的界面,使用户能够以三维方式查看机器人模型、传感器数据和环境地图等。它支持多种类型的可视化对象,包括点云、网格模型、标记、路径、激光扫描和相机图像等。

        使用:

        打开两个终端

# 一个终端输入
roscore

# 另一个输入
rviz

        这里,对该窗口作简单介绍

        添加选项

        我们拿添加image为例

         那我们打开usb_cam,就可以有图像话题产生了,然后就可以看到啦

roslaunch usb_cam usb_cam-test.launch

        那么,我们对rviz的了解就可以结束了,感兴趣的小伙伴可以自己再研究研究。

二、librviz和Qt的UI结合

        说明:

        该部分意在将我们上面的rviz的可裁减功能融入我们自己设计的UI界面中,比如我们可以做一个显示机器人模型和我们相机识别AR码结果显示的一个自定义UI。那么开始,我建议读者可以先阅读本博主上一篇博客的第四个模块,他讲述了将ROS和Qt结合的一个基础,以及第五个模块,讲述了第三方库和Qt结合开发的一些知识。Ubuntu下基于ROS开发QT人机交互界面和PCL点云处理软件_ros qt pcl-CSDN博客文章浏览阅读889次,点赞22次,收藏27次。仁兄加油吧,活到老,学到老。持续关注博主,将会更新PCL的滤波、平滑、拟合(贪婪三角化)等点云操作方法。_ros qt pcl利用ROS做机器人手眼标定和Qt+rviz+图片话题显示的UI设计https://blog.csdn.net/qq_60640693/article/details/134811948?spm=1001.2014.3001.5501        当然的当,你也可以不看,其实我只是想增加我的浏览量…..哈哈哈哈;不过通过上篇文章确实可以学到东西,但是只看本篇也是可以的了。

        开发步骤:

        1、前言

        首先说明一下,我已有的文件结构

        那么实际上,我们只需要封装一个qt+rviz的包就好了。

        2、创建框架

        创建工作空间

mkdir -p cam_ui/src
cd cam_ui/
catkin_make

        创建qrviz功能包

cd src/
catkin_create_pkg qrviz roscpp

        用QtCreator打开该工作空间并对该功能包编写

       

        这个时候,就可以用QtCreator再创建一个界面项目,并把他的main.cpp、ui文件和widget.h、widget.cpp文件移到我们功能包下(该部分在上篇文章中 模块四:Qt制作ROS人机交互界面 有提及)。

        这是移动后效果

        接下来双击widget.ui文件设计界面

        然后回到编辑源码页面,修改CMakeLists.txt文件和增加rosnode(前两个部分我在上一片有提及)和Qrviz类(这部分看下面图片的注意事项),这部分直接将我开源的代码复制过去研究就好了。

        把这些对应的cpp和h、hpp文件移到src和include文件夹下,然后就可以双击CMakeLists.txt修改了,修改完成后,就可以编译了。

        3、源码文件

        CMakeLists.txt文件

#设置cmake版本号
cmake_minimum_required(VERSION 3.0.2)
#设置项目名称
project(qrviz)

#寻找ros包 赋予catkin
find_package(catkin REQUIRED COMPONENTS
  roscpp
  rviz
  std_msgs
  sensor_msgs
  image_transport
  cv_bridge
  )

#声明联合编译为ros包 不然roslaunch和rosrun调不起
catkin_package()

#打开QT moc(自定义信号和槽函数生成功能生成信号的moc_xxx.cpp文件) RCC(qrc资源文件) UIC(负责处理ui文件,生成对应的ui_xxxx.h文件)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)


#寻找QT包 有QT6就是6 没有就是QT5
find_package(Qt5 COMPONENTS Widgets Core Gui REQUIRED)



#########################################  源码、ui文件和头文件  ################################################
set(SOURCES
    src/widget.ui
    src/widget.cpp
    src/main.cpp
    src/qrviz.cpp
    src/rosnode.cpp
)
#这里可以不设置这个 直接把这两个放在src下编译 也行
set(HEADERS
   include/widget.h
   include/qrviz.hpp
   include/rosnode.h
)

###############################################################################################################

#加载头文件到环境中
include_directories(
    include #当前目录的include
    ${catkin_INCLUDE_DIRS} #ros头文件
)

#源码编译为
add_executable(ui ${SOURCES} ${HEADERS}
)

#链接所有动态链接库
target_link_libraries(ui Qt5::Widgets Qt5::Core Qt5::Gui ${catkin_LIBRARIES})

        main.cpp文件

#include "widget.h"

#include <QApplication>
#include <rosnode.h>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    ros::init(argc,argv,"ui");
    Widget w;
    Rosnode n; //实例化一个rosnode对象(该类和方法在rosnode.h和rosnode.cpp中实现)
    QObject::connect(&n,&Rosnode::pubimage,&w,&Widget::getimage); //绑定对象信号和槽函数
    QObject::connect(&n,&Rosnode::pubparam,&w,&Widget::getparam);
    QObject::connect(&w,&Widget::startgetparam,&n,&Rosnode::startpubparam);
    w.startrviz();
    w.show();
    return a.exec();
}

        widget.h文件

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QImage>
#include <QMap>

#include <qrviz.hpp>

QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    void startrviz();
    ~Widget();

private:
    Ui::Widget *ui;
    Qrviz *my_rviz;

    QMap<QString,QString> param; //接收参数map
signals:
    void startgetparam();
public slots:
    void getimage(QImage im);
    void getparam(QMap<QString,QString>pa);
};
#endif // WIDGET_H

        widget.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
}

void Widget::startrviz()
{
    emit startgetparam(); //开始获得参数
    my_rviz=new Qrviz(ui->verticalLayout);
    my_rviz->display_grid();
    my_rviz->set_fixedframe(param["fixed_frame"]); //传递参数给qrviz
    my_rviz->display_model(param["robot_model"]);
    //my_rviz->display_imag(param["image_topic"]);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::getimage(QImage im)
{
    ui->label->setPixmap(QPixmap::fromImage(im));
}

void Widget::getparam(QMap<QString, QString> pa)
{
    param.unite(pa); //得到参数存到param中
}

        rosnode.h

#ifndef ROSNODE_H
#define ROSNODE_H

#include <QThread>
#include <QImage>
#include <QMap>

#include <sensor_msgs/Image.h>
#include <cv_bridge/cv_bridge.h>
#include <ros/ros.h>

// 子线程类
class Rosnode : public QThread //继承QThread(线程类)
{
    Q_OBJECT

public:
    void run() override; //重写run函数
    Rosnode();
    void sub_callback(const sensor_msgs::Image::ConstPtr &msg_); //图片消息回调函数
    void getparam(QString paramName); //ros得到参数文件并存储到一个Qmap中
    QImage cvMat2QImage(const cv::Mat &mat); //把图片转化为Qimage

    ros::NodeHandle nh; //定义一个ros节点句柄,用于操作ros方法
    ros::Publisher pub; //话题发布器
    ros::Subscriber sub; //话题订阅器

    QMap<QString,QString> param; //参数存储map

signals:
    void pubimage(QImage im); //发布图片信号给UI页面接收
    void pubparam(QMap<QString,QString> pa); //发布参数map给qrviz对象控制

public slots:
    void startpubparam(); //靠UI页面来控制是否开始传递读取参数

};

#endif // ROSNODE_H

        rosnode.cpp

#include "rosnode.h"

void Rosnode::run()
{

}

Rosnode::Rosnode()
{
    /*读取三个参数文件参数*/
    getparam("fixed_frame");
    getparam("image_topic");
    getparam("robot_model");
    sub=nh.subscribe(param["image_topic"].toStdString(),1,&Rosnode::sub_callback,this); //绑定消息回调函数
}

/*有图片消息过来就以信号抛出给UI了*/
void Rosnode::sub_callback(const sensor_msgs::Image::ConstPtr &msg_)
{
    cv_bridge::CvImagePtr cv_ptr;
    try
    {
        cv_ptr = cv_bridge::toCvCopy(msg_,msg_->encoding);
        QImage im = cvMat2QImage(cv_ptr->image);
        emit pubimage(im);
    }
    catch (cv_bridge::Exception&e)
    {
        ROS_ERROR(e.what());
        return;
    }


}

void Rosnode::getparam(QString paramName)
{
    std::string vale_s;
    nh.getParam(paramName.toStdString(),vale_s);
    QString vale(vale_s.data());
    param[paramName]=vale;
}
void Rosnode::startpubparam()
{
    emit pubparam(param);
}
QImage Rosnode::cvMat2QImage(const cv::Mat &mat)
{
    QImage image;
    switch(mat.type())
    {
    case CV_8UC1:
        // QImage构造:数据,宽度,高度,每行多少字节,存储结构
        image = QImage((const unsigned char*)mat.data, mat.cols, mat.rows, mat.step, QImage::Format_Grayscale8);
        break;
    case CV_8UC3:
        image = QImage((const unsigned char*)mat.data, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
        //image = image.rgbSwapped(); // BRG转为RGB(颜色变成灰色)
        //Qt5.14增加了Format_BGR888
        //image = QImage((const unsigned char*)mat.data, mat.cols, mat.rows, mat.cols * 3, QImage::Format_BGR888);
        break;
    case CV_8UC4:
        image = QImage((const unsigned char*)mat.data, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);
        break;
    case CV_16UC4:
        image = QImage((const unsigned char*)mat.data, mat.cols, mat.rows, mat.step, QImage::Format_RGBA64);
        image = image.rgbSwapped(); // BRG转为RGB
        break;
    }
    return image;
}

        qrviz.hpp文件

#ifndef QRVIZ_HPP
#define QRVIZ_HPP

#include <QObject>

#include <ros/ros.h>

#include <rviz/visualization_manager.h>
#include <rviz/render_panel.h>
#include <rviz/display.h>
#include <rviz/tool_manager.h>
#include<rviz/tool.h>
#include <rviz/default_plugin/view_controllers/orbit_view_controller.h>
#include <rviz/view_manager.h>

#include <QVBoxLayout>

class Qrviz
{
public:
    Qrviz(QVBoxLayout *layout); //重写构造函数传入一个布局地址
    void display_grid(); //展示网格
    void set_fixedframe(QString frame); //设置相机坐标系
    void display_imag(QString topic); //设置图片话题
    void display_model(QString model); //设置机器人模型


private:
    rviz::RenderPanel *render_panel_; //rviz显示容器
    rviz::VisualizationManager* manager_; //rviz控制器
};

#endif // QRVIZ_HPP

        qrviz.cpp

#include "qrviz.hpp"

Qrviz::Qrviz(QVBoxLayout *layout)
{
    render_panel_=new rviz::RenderPanel();  //创建rviz显示容器,其本质是继承QWidget类,因此可将其看成一个窗口控件
    layout->addWidget(render_panel_); //将rviz显示容器加入传入的布局器中
    manager_=new rviz::VisualizationManager(render_panel_); //获取可视化rviz的控制对象,后面直接操作这个
    /*前三步把Qt窗口的布局器和rviz的显示窗口绑定,并绑定了一个供操作rviz的接口manager_*/

    render_panel_->initialize(manager_->getSceneManager(),manager_);  //绑定交互信号(初始化camera ,实现放大 缩小 平移等操作)

    manager_->initialize();//初始化
    manager_->removeAllDisplays();//删除所有图层
    manager_->startUpdate();//更新所有图层
}


void Qrviz::display_grid()//添加网格
{
    /*
     * Display* createDisplay( const QString& class_lookup_name, const QString& name, bool enabled );
     * 创建图层函数,其中class_lookup_name:还可以取“rviz/PointCloud2”,“rviz/RobotModel”,"rviz/TF"等:
       图层创建好之后要设置图层的各个属性值,属性值也可以根据rviz图形界面右侧来设置:
       subProp( QString propertyName )->setValue(Qvariant value)(键值对);
     */
    rviz::Display* grid_ =manager_->createDisplay("rviz/Grid","adjustable grid",true);
    grid_->subProp("Line Style")->setValue("Billboards");
    grid_->subProp("Color")->setValue(QColor(125,125,125));
}

void Qrviz::set_fixedframe(QString frame)
{
    manager_->setFixedFrame(frame);
}

void Qrviz::display_imag(QString topic)
{
    rviz::Display* imag_ =manager_->createDisplay("rviz/Image","xs image",true);
    imag_->subProp("Image Topic")->setValue(topic);
}

void Qrviz::display_model(QString model)
{
    rviz::Display* model_=manager_->createDisplay("rviz/RobotModel","robot",true);
    model_->setDescription(model);
}

        那么,到此为止我们就搞定了最重要的一个环节;但是由于我代码采用的参数是由外部文件来提供的,所以我们需要一个param的文件夹下的qrviz.yaml文件和对应的launch文件。

        qrviz.yaml

# 设置qrviz的参数
# fixed_frame 相机所在坐标系名称
# image_topic 图像显示订阅话题
# robot_model 机器人模型名

fixed_frame: /base_link
image_topic: /aruco_single/result
robot_model: robot_description

        qrviz.launch

<launch>
<!-- 加载参数文件的参数 -->
    <rosparam file="$(find qrviz)/param/qrviz.yaml" command="load"/>
    <node name="ui" pkg="qrviz" type="ui" output="screen" required="true"/>
</launch>

        这里,我提供我的项目文件 链接 ,提取码: xs66,其中包括aruco_ros、handeye-calib、krp_description(我自己的机器人模型)、qrviz、bringup(启动功能包);下载、编译可以

# 注意/handeye-calib/launch/aruco/aruco_start_usb_cam.launch里面的摄像头驱动号
# <arg name="video_device"     default="/dev/video2"/> 可能是其他号
roslaunch bringup bringup.launch

        运行效果

        注意:

        如果出现下述问题

总结:

        博主说:

        虽然这个过程曲折且艰辛,但是不经历风雨,如何见彩虹啊;诸位仁兄,还得学习啊,每日三省吾身……哈哈哈哈哈哈。

        废话少说,后面我会继续更新PCL、Qt、ROS以及机械臂相关知识的,知识点杂,大家挑有用的看吧。

版权声明:本文为博主作者:山半仙xs原创文章,版权归属原作者,如果侵权,请联系我们删除!

原文链接:https://blog.csdn.net/qq_60640693/article/details/135546696

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
乘风的头像乘风管理团队
上一篇 2024年4月16日
下一篇 2024年4月16日

相关推荐