常见错误
  1. 编译不成功


    解决办法
    删除工作空间的build和devel
    cd catkin_qt/
    catkin_make
  2. qt下编译失败


    https://blog.csdn.net/weixin_50303783/article/details/117359878?spm=1001.2014.3001.5501
  3. qt下编译显示找不到共享文件


    配置qtcreator
    sudo vim /usr/bin/qtcreator
    添加如下内容: QT_HOME更改为自己qt安装路径的bin目录
    1
    2
    3
    4
    #!/bin/sh 
    export QT_HOME=/home/xxxx/Qtxxx/Tools/QtCreator/bin
    export QT_HOME=/home/lixiao/Qt5.9.9/Tools/QtCreator/bin
    $QT_HOME/qtcreator $*
    更改可执行权限
    sudo chmod a+x /usr/bin/qtcreator
    终端输入:
    qtcreator
    不要直接点开软件
配置流程

转载古月居 http://www.guyuehome.com/6058
ROS Qt5 librviz人机交互界面开发一(配置QT环境)

  1. 首先安装ros对qt pkg的支持

    1
    2
    3
    sudo apt install update
    sudo apt-get install ros-melodic-qt-create
    sudo apt-get install ros-melodic-qt-build
    这样就能通过:catkin_create_qt_pkg命令创建ros gui包了:
    在src目录下创建包:
    1
    2
    cd catkin_ws/src
    catkin_create_qt_pkg qt_ros_test roscpp rviz
  2. 安装qtcreator


    https://s3.jcloud.sjtu.edu.cn/899a892efef34b1b944a19981040f55b-oss01/rsync/qt/921fa12ae4f32a039557388302b3796dcb5915dd
    更改安装包的可执行权限
    1
    chmod a+x qt-opensource-linux-x64-5.9.9.run
    双击安装包名安装
    断网安装
    安装组件选择上Desktop gcc 64-bit
  3. 配置qtcreator

    1
    sudo vim /usr/bin/qtcreator
    添加如下内容: QT_HOME更改为自己qt安装路径的bin目录
    1
    2
    3
    4
    #!/bin/sh 
    export QT_HOME=/home/xxxx/Qtxxx/Tools/QtCreator/bin
    export QT_HOME=/home/lixiao/Qt5.9.9/Tools/QtCreator/bin
    $QT_HOME/qtcreator $*
    更改可执行权限
    1
    sudo chmod a+x /usr/bin/qtcreator
    终端输入:
    qtcreator
    文件->打开项目->选择工作空间下src下的cmakelist.txt(==注意并非功能包下的==)
    打开后点击项目: 将build的构建目录改为当前工作空间的build文件夹
    然后返回编辑右键项目->执行cmake如果弹出提示框点击第一个按钮change,如果报错http://www.guyuehome.com/6058#comment
  4. 更改功能包main_window.hpp


    由于Q4t中包含QMainWindow在QtGui中,在Qt5中更改为QtWidgets类中,所以需要作更改:进入工作空间下的qt功能包比如上面创建的qt_ros_test ./include/功能包名/main_window.hpp
    1
    2
    3
    #include<QtGui/QMainWindow>
    改为
    #include<QtWidgets/QMainWindow>
  5. 运行可执行文件


    在左侧项目->run->运行配置 更改要运行的可执行文件名称,并点击绿色三角形运行即可
  1. 原理主要就是订阅机器人的odom话题,然后利用信号与槽更新ui仪表盘控件的信息

    一 创建qt项目功能包
    1
    2
    3
    catkin_create_qt_pkg命令创建ros gui包了: 在src目录下创建包:
    cd catkin_ws/src
    catkin_create_qt_pkg qt_ros_test
    二 更改功能包main_window.hpp
    1
    2
    3
    4
    qt功能包比如上面创建的qt_ros_test ./include/功能包名/main_window.hpp
    #include<QtGui/QMainWindow>
    改为
    #include<QtWidgets/QMainWindow>
    三 返回编辑右键项目->执行cmake
    四 开始编写
    1. 一在工作空间下的src文件夹->qt功能包->include文件夹->qt功能包同名文件夹->建立文件CCtrlDashBoard.hpp

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      #ifndef CCTRLDASHBOARD_H
      #define CCTRLDASHBOARD_H

      #include <QWidget>

      class CCtrlDashBoard : public QWidget
      {
      Q_OBJECT
      public:
      enum StyleType {
      ST_DEFAULT=0,
      ST_ARCBAR
      };
      explicit CCtrlDashBoard(QWidget *parent = nullptr, StyleType type=ST_DEFAULT);

      void setValue(qreal value){
      m_DashValue = value;
      update();
      }
      void setBackGroundColor(QColor color){
      m_BgColor=color;
      update();
      }
      void setFrontColor(QColor color){
      m_FrontColor=color;
      update();
      }
      void setBorderColor(QColor color){
      m_BorderColor=color;
      update();
      }
      void setUnitString(QString str){
      m_StrUnit=str;
      update();
      }

      void drawBackGround(QPainter *painter, qreal hlafWidth);
      void drawScaleDials(QPainter *painter, qreal hlafWidth);
      void drawIndicator(QPainter *painter, qreal hlafWidth);
      void drawIndicatorBar(QPainter *painter, qreal hlafWidth);
      signals:

      public slots:
      protected:
      virtual void paintEvent(QPaintEvent * event);

      private:
      int m_StartAngle;
      int m_EndAngle;
      int m_StyleType;

      qreal m_LineLength;
      qreal m_DashValue;
      qreal m_MaxValue;
      qreal m_MinValue;
      qreal m_DashNum;

      QColor m_BgColor;
      QColor m_FrontColor;
      QColor m_BorderColor;
      QString m_StrUnit;

      qreal m_MaxBorderRadius;
      qreal m_MinBorderRadius;
      qreal m_DialsRadius;
      };

      #endif // CCTRLDASHBOARD_H
    2. 二在工作空间下的src文件夹->qt功能包->src文件夹->建立文件CCtrlDashBoard.cpp

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
      100
      101
      102
      103
      104
      105
      106
      107
      108
      109
      110
      111
      112
      113
      114
      115
      116
      117
      118
      119
      120
      121
      122
      123
      124
      125
      126
      127
      128
      129
      130
      131
      132
      133
      134
      135
      136
      137
      138
      139
      140
      141
      142
      143
      144
      145
      146
      147
      148
      149
      150
      151
      152
      153
      154
      155
      156
      157
      158
      159
      160
      161
      162
      163
      164
      165
      166
      167
      168
      169
      170
      171
      172
      173
      174
      175
      176
      177
      178
      179
      180
      181
      182
      183
      184
      185
      186
      187
      188
      189
      190
      191
      192
      193
      194
      195
      196
      197
      198
      199
      200
      201
      202
      203
      204
      205
      206
      207
      208
      209
      210
      211
      212
      213
      214
      215
      216
      217
      218
      219
      220
      221
      222
      223
      224
      225
      226
      227
      228
      229
      230
      231
      232
      233
      234
      235
      236
      237
      238
      239
      240
      241
      242
      243
      244
      245
      246
      247
      248
      249
      250
      251
      252
      253
      254
      255
      256
      257
      258
      259
      260
      261
      262
      263
      264
      265
      266
      267
      268
      269
      270
      271
      272
      273
      274
      275
      #include "../include/qt_ros_test/CCtrlDashBoard.hpp"
      #include <QPainter>
      #include <QDebug>
      #include <qmath.h>

      CCtrlDashBoard::CCtrlDashBoard(QWidget *parent, StyleType type) :
      QWidget(parent),
      m_StyleType(type)
      {
      m_BorderColor = QColor(172,172,172);
      m_BgColor = QColor(40,40,40);
      m_FrontColor = Qt::white;

      m_DashValue= 0;
      m_MinValue = 0;
      m_MaxValue = 100;
      m_DashNum = 1;
      m_LineLength=0;

      m_StartAngle=90; //510
      m_EndAngle=0; //120
      update();
      }

      void CCtrlDashBoard::drawBackGround(QPainter *painter, qreal hlafWidth)
      {
      m_MaxBorderRadius = ((hlafWidth*5)/6);
      qreal startX=hlafWidth-m_MaxBorderRadius;
      painter->save();
      painter->setPen(m_BorderColor);
      painter->setBrush(m_BorderColor);

      QPainterPath bigCircle;
      bigCircle.addEllipse(startX, startX, (m_MaxBorderRadius*2), (m_MaxBorderRadius*2));

      m_MinBorderRadius = m_MaxBorderRadius-15;
      startX=hlafWidth-m_MinBorderRadius;
      QPainterPath smallCircle;
      smallCircle.addEllipse(startX, startX, (m_MinBorderRadius*2), (m_MinBorderRadius*2));

      QPainterPath path = bigCircle - smallCircle;
      painter->drawPath(path);
      painter->restore();

      painter->save();
      painter->setBrush(m_BgColor);
      painter->drawEllipse(startX,startX,(m_MinBorderRadius*2), (m_MinBorderRadius*2));
      if(m_DashValue==0){
      QString speed = "0.0 cm/s";
      painter->drawText(startX+85,startX+170,speed);
      }
      else{
      QString speed = QString::number(m_DashValue).mid(0,3) + " cm/s";
      painter->drawText(startX+85,startX+170,speed);
      }
      painter->restore();
      m_DialsRadius = m_MinBorderRadius-10;
      if(m_DialsRadius < 0){
      m_DialsRadius=2;
      }
      }
      void CCtrlDashBoard::drawScaleDials(QPainter *painter, qreal hlafWidth)
      {
      qreal tSteps = (m_MaxValue - m_MinValue)/m_DashNum; //相乘后的值是分的份数
      qreal angleStep = 1.0*(360.0-m_StartAngle - m_EndAngle) / tSteps; //每一个份数的角度
      QPen pen ;
      pen.setColor(m_FrontColor); //推荐使用第二种方式
      painter->save();
      painter->translate(hlafWidth,hlafWidth);
      painter->rotate(m_StartAngle);
      m_LineLength = (hlafWidth/16);
      qreal lineStart = m_DialsRadius-4*m_LineLength-m_LineLength;
      qreal lineSmStart = m_DialsRadius-4*m_LineLength-m_LineLength/2;
      qreal lineEnd = m_DialsRadius-4*m_LineLength;
      for (int i = 0; i <= tSteps; i++)
      {
      if(i>80) pen.setColor(QColor(250,0,0));
      if (i % 10 == 0)//整数刻度显示加粗
      {
      pen.setWidth(2); //设置线宽
      painter->setPen(pen); //使用面向对象的思想,把画笔关联上画家。通过画家画出来
      painter->drawLine(lineStart,lineStart, lineEnd, lineEnd); //两个参数应该是两个坐标值
      //painter->drawText(lineEnd+6,lineEnd+6, tr("%1").arg(m_MinValue+i));
      }
      else
      {
      pen.setWidth(1);
      painter->setPen(pen);
      painter->drawLine(lineSmStart, lineSmStart, lineEnd, lineEnd); //两个参数应该是两个坐标值
      }
      painter->rotate(angleStep);
      }
      pen.setColor(m_FrontColor);
      painter->restore();
      painter->save();
      painter->setPen(pen);
      //m_startAngle是起始角度,m_endAngle是结束角度,m_scaleMajor在一个量程中分成的刻度数
      qreal startRad = ( 315-m_StartAngle) * (3.14 / 180);
      qreal deltaRad = (360-m_StartAngle - m_EndAngle) * (3.14 / 180) / tSteps;
      qreal sina,cosa;
      qreal x, y;
      QFontMetricsF fm(this->font());
      double w, h, tmpVal;
      QString str;
      painter->translate(hlafWidth,hlafWidth);
      lineEnd = m_MinBorderRadius-8;
      for (int i = 0; i <= tSteps; i++)
      {
      if (i % 10 == 0)//整数刻度显示加粗
      {
      sina = qSin(startRad - i * deltaRad);
      cosa = cos(startRad - i * deltaRad);

      tmpVal = 1.0 * i *((m_MaxValue - m_MinValue) / tSteps) + m_MinValue;
      str = QString( "%1" ).arg(tmpVal); //%1作为占位符 arg()函数比起 sprintf()来是类型安全的
      w = fm.size(Qt::TextSingleLine,str).width();
      h = fm.size(Qt::TextSingleLine,str).height();
      x = lineEnd * cosa - w / 2;
      y = -lineEnd * sina + h / 4;
      painter->drawText(x, y, str); //函数的前两个参数是显示的坐标位置,后一个是显示的内容,是字符类型""
      }
      }
      painter->restore();
      }

      void CCtrlDashBoard::drawIndicator(QPainter *painter, qreal hlafWidth)
      {
      QPolygon pts;
      pts.setPoints(3, -8,0, 8,0, 0,(int)m_DialsRadius-20); /* (-2,0)/(2,0)/(0,60) *///第一个参数是 ,坐标的个数。后边的是坐标
      painter->save();
      painter->translate(hlafWidth, hlafWidth);
      painter->rotate(m_StartAngle-45);

      if(m_DashValue>0){
      qreal tSteps = (m_MaxValue - m_MinValue)/m_DashNum; //相乘后的值是分的份数
      qreal angleStep = 1.0*(360.0-m_StartAngle - m_EndAngle) / tSteps; //每一个份数的角度
      double degRotate = angleStep*tSteps*(m_DashValue/100.0)+angleStep;

      //画指针
      //qDebug() <<"degRotate =="<<degRotate<<"m_DashValue =="<<m_DashValue<<m_StartAngle<<m_DialsRadius<<hlafWidth;
      if(m_DashValue == 99){
      painter->rotate(m_EndAngle-m_StartAngle); //顺时针旋转坐标系统
      }else
      {
      painter->rotate(degRotate); //顺时针旋转坐标系统
      }

      }
      QRadialGradient haloGradient(0, 0, hlafWidth/2, 0, 0); //辐射渐变
      haloGradient.setColorAt(0, QColor(255,69,0));
      haloGradient.setColorAt(1, QColor(255,0,0));
      painter->setPen(Qt::white); //定义线条文本颜色 设置线条的颜色
      painter->setBrush(haloGradient);//刷子定义形状如何填满 填充后的颜色
      painter->drawConvexPolygon(pts); //这是个重载函数,绘制多边形。
      painter->restore();

      //画中心点
      QColor niceBlue(150, 150, 200);
      QConicalGradient coneGradient(0, 0, -90.0); //角度渐变
      coneGradient.setColorAt(0.0, Qt::darkGray);
      coneGradient.setColorAt(0.2, niceBlue);
      coneGradient.setColorAt(0.5, Qt::white);
      coneGradient.setColorAt(1.0, Qt::darkGray);
      painter->save();
      painter->translate(hlafWidth,hlafWidth);
      painter->setPen(Qt::NoPen); //没有线,填满没有边界
      painter->setBrush(coneGradient);
      painter->drawEllipse(-10, -10, 20, 20);
      painter->restore();
      }

      void CCtrlDashBoard::drawIndicatorBar(QPainter *painter, qreal hlafWidth)
      {
      // 渐变色
      painter->save();
      painter->translate(hlafWidth,hlafWidth);
      qreal lineEnd = m_DialsRadius-3*m_LineLength;
      QRadialGradient gradient(0, 0, lineEnd);
      gradient.setColorAt(0, Qt::white);
      gradient.setColorAt(1.0, Qt::blue);
      painter->setBrush(gradient);

      // << 1(左移1位)相当于radius*2 即:150*2=300
      //QRectF(-150, -150, 300, 300)
      QRectF rect(-lineEnd, -lineEnd, lineEnd*2, lineEnd*2);
      QPainterPath path;
      path.arcTo(rect, m_StartAngle, 270);

      // QRectF(-120, -120, 240, 240)
      QPainterPath subPath;
      subPath.addEllipse(rect.adjusted(10, 10, -10, -10));

      // path为扇形 subPath为椭圆
      path -= subPath;
      painter->setPen(Qt::NoPen);
      painter->rotate(m_StartAngle+45);
      painter->drawPath(path);
      painter->restore();


      qreal degRotate=0.1;
      if(m_DashValue>0){
      qreal tSteps = (m_MaxValue - m_MinValue)/m_DashNum; //相乘后的值是分的份数
      qreal angleStep = 1.0*(360.0-m_StartAngle - m_EndAngle) / tSteps; //每一个份数的角度
      degRotate = angleStep*tSteps*(m_DashValue/100.0)+angleStep;

      //画指针
      //qDebug() <<"degRotate =="<<degRotate<<"m_DashValue =="<<m_DashValue<<m_StartAngle<<m_DialsRadius<<hlafWidth;
      /*if(m_DashValue == 99){
      painter->rotate(m_EndAngle-m_StartAngle); //顺时针旋转坐标系统
      }else
      {
      painter->rotate(degRotate); //顺时针旋转坐标系统
      }*/
      }

      painter->save();
      painter->translate(hlafWidth, hlafWidth);

      QRadialGradient ftGradient(0, 0, lineEnd);
      ftGradient.setColorAt(0, Qt::white);
      ftGradient.setColorAt(1.0, Qt::darkYellow);
      painter->setBrush(ftGradient);

      // << 1(左移1位)相当于radius*2 即:150*2=300
      //QRectF(-150, -150, 300, 300)
      QRectF ftRect(-lineEnd, -lineEnd, lineEnd*2, lineEnd*2);
      QPainterPath ftPath;
      ftPath.arcTo(ftRect, m_EndAngle-m_StartAngle, -degRotate);
      // path为扇形 subPath为椭圆
      ftPath -= subPath;
      painter->rotate(m_StartAngle-45);
      painter->drawPath(ftPath);
      painter->restore();

      QPolygon pts;
      int pointLength=lineEnd-12;
      pts.setPoints(3, -6,pointLength-10, 6,pointLength-10, 0,pointLength);
      painter->save();
      painter->translate(hlafWidth, hlafWidth);
      painter->rotate(m_StartAngle-45);

      if(m_DashValue == 99){
      painter->rotate(m_EndAngle-m_StartAngle); //顺时针旋转坐标系统
      }else
      {
      painter->rotate(degRotate); //顺时针旋转坐标系统
      }
      painter->setPen(Qt::white); //定义线条文本颜色 设置线条的颜色
      painter->setBrush(Qt::blue);//刷子定义形状如何填满 填充后的颜色
      painter->drawConvexPolygon(pts); //这是个重载函数,绘制多边形。
      painter->restore();
      }

      void CCtrlDashBoard::paintEvent(QPaintEvent * event)
      {
      QPainter p(this);
      qreal width = qMin((this->width()>>1), (this->height()>>1));

      p.setRenderHints(QPainter::Antialiasing|QPainter::TextAntialiasing);

      drawBackGround(&p, width);

      drawScaleDials(&p, width);
      switch(m_StyleType)
      {
      case ST_DEFAULT:
      drawIndicator(&p, width);
      break;
      case ST_ARCBAR:
      drawIndicatorBar(&p, width);
      break;
      }
      }

    3. 三在工作空间下的src文件夹->qt功能包->src文件夹->main_window.cpp


      需要在ui中添加一个widget(需要固定size),我这里为widget_speed_x,widget_speed_y
      找到提示区域Implementation [MainWindow]下的
      MainWindow::MainWindow(int argc, char* argv, QWidget parent)
      : QMainWindow(parent)
      , qnode(argc,argv)
      函数里的Auto Start提示区域
      添加代码:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      //init ui
      speed_x_dashBoard=new CCtrlDashBoard(ui.widget_speed_x);
      speed_y_dashBoard=new CCtrlDashBoard(ui.widget_speed_y);
      speed_x_dashBoard->setGeometry(ui.widget_speed_x->rect());
      speed_y_dashBoard->setGeometry(ui.widget_speed_y->rect());
      speed_x_dashBoard->setValue(0);
      speed_y_dashBoard->setValue(0);
      ui.horizontalSlider_linera->setValue(20);
      ui.horizontalSlider_raw->setValue(20);
    4. 订阅odom话题:


      一创建订阅者:
      在工作空间下的src文件夹->qt功能包->src文件夹->qnode.cpp
      在bool QNode::init()两个函数中添加
      1
      odom_sub = n.subscribe("odom",1000,&QNode::odom_raw_callback,this);
      二回调函数:
      取出话题中的数据给信号,并在有数据时发送该信号
      emit就是发送信号
    5. qnode.hpp中的Q_SIGNALS:加入
      void speed_vel(float,float);
      两个参数均为float,分别代表x和y方向的速度。一旦进入回调函数就发送这个信号
    6. qnode.cpp中下方新起一行建立回调函数
      1
      2
      3
      4
      5
      void QNode::odom_raw_callback(const nav_msgs::Odometry &msg)
      {
      emit speed_vel(msg.twist.twist.linear.x,msg.twist.twist.linear.y);

      }
      三 数据传递给ui
      在main_window.cpp中创建一个connect以及槽函数,当收到speed_vel信号时执行槽函数slot_update_dashboard(float,float)。
      1
      connect(&qnode,SIGNAL(speed_vel(float,float)),this,SLOT(slot_update_dashboard(float,float)));
      这个槽函数会把信号携带速度的信息提取出来并显示。如果值为负数,则在文本框中显示负向。如果值为正数,则在文本框中显示正向。同时由于显示在仪表盘中的数据是厘米每秒所以需要进行单位换算。
      1
      2
      3
      4
      5
      6
      void MainWindow::slot_update_dashboard(float x,float y)
      { ui.label_dir_x->setText(x>0?"正向":"反向");
      ui.label_dir_y->setText(y>0?"正向":"反向");
      speed_x_dashBoard->setValue(abs(x)*100);
      speed_y_dashBoard->setValue(abs(y)*100);
      }
      槽函数在main_window.hpp中的public Q_SLOTS:声明
      1
      void slot_update_dashboard(float,float);
环境搭建

第一步
在qt官网中下载linux版本的qt进行安装,断网跳过注册,选择gcc编译。
第二步
安装依赖ros-melodic-qt-create和ros-melodic-qt-build。
第三步
创建qt功能包。
第四步
编译ROS工程打开qtcreator,在打开项目选择工作空间catkin_qt下的src文件夹里的CmakeList.txt文件。随后配置build目录为工作空间下的build文件夹。
第五步
编写ros节点,步骤大概分为在节点初始化函数中初始化ros节点、在master中注册节点、发布话题。

编写键盘控制界面

第一步ui设计
在ui界面设计中放置8个push button参考ros自带的控制节点,分别把这8个按钮的显示文本为u、i、o、j 、l、 m、 ,、.。
第二步
在Qnode::init函数中初始化节点,创建一个发布器cmd_vel_pub用来发布速度控制话题,话题名为cmd_vel。建立函数set_cmd_vel,该回调函数传入按钮,线速度,角速度三个参数时会根据绑定的字典得到控制的方向和速度,随后把数据传给消息类型为geometry_msgs::Twist的变量。随后通过发布器把这个控制话题发布出去。

编写电量显示界面

第一步ui设计
放置几个label用来显示文字个图标,放置一个progressBar显示电池电量的百分比。在resources中右击open in editor添加图片方便打包
第二步
在Qnode::init函数中初始化节点,创建一个订阅器power_sub用来订阅电池信息的话题,话题名为voltage,收到该话题后执行回调函数power_callback,因为需要把信息显示到窗口上。所以在qnode.hpp中声明一个信号power_vel,参数为float类型的。一旦进入回调函数就发送这个信号
第三步
在main_window.cpp中创建一个connect,当收到power_vel信号时执行槽函数slot_update_power(float)。这个槽函数会把信号携带的信息提取出来并显示。显示百分比时把9.6v作为电池电量的最小值,11.7v作为电池电量最大值。依据的是yahboom小车。

编写odom速度信息显示界面

第一步ui设计
放置tabWidget用来放置两个widget,一个用来放置x轴的速度仪表盘,名字为widget_speed_x,另一个用来放置y轴的速度仪表盘,名字为widget_speed_y。放置四个label显示速度的正反向。
第二步
在Qnode::init函数中初始化节点,创建一个订阅器odom_sub用来订阅odom信息的话题,话题名为odom,收到该话题后执行回调函数odom_raw_callback,因为需要把信息显示到窗口上所以在qnode.hpp中声明一个信号speed_vel,两个参数均为float,分别代表x和y方向的速度。一旦进入回调函数就发送这个信号。
第三步
在main_window.cpp中创建一个connect,当收到speed_vel信号时执行槽函数slot_update_dashboard(float,float)。这个槽函数会把信号携带速度的信息提取出来并显示。如果值为负数,则在文本框中显示负向。如果值为正数,则在文本框中显示正向。同时由于显示在仪表盘中的数据是厘米每秒所以需要进行单位换算。

编写摄像头画面显示界面

第一步
在CmakeLists.txt文件中添加三个依赖项cv_bridge、image_transport、sensor_msgs
随后包含三者的头文件。
第二步ui设计
放置一个label用来显示摄像头的图像,放置一个Line Edit用来输入订阅的图像话题的话题名,放置一个Push Button用来触发订阅话题的信号。
第三步
在头文件中声明图像话题的订阅者和收到图像话题后的回调函数以及把图像格式转化为qt支持的图像显示的函数Mat2QImage。
第四步在main_window.cpp中创建一个connect,当收到按钮的点击信号时执行槽函数slot_sub_image()。这个槽函数会把Line Edit上的文本信息作为参数传给接口函数sub_image(QString topic_name),而这个接口函数会创建一个图像话题的订阅器。当收到图像话题时执行回调函数,回调函数把收到的图像处理成qt可以显示的图像后发送自定义信号image_val(QImage)。在main_window.cpp中创建一个connect,当收到image_val(QImage)信号时执行槽函数slot_update_image(QImage),这个槽函数会把该信号携带的qt可以显示的图像内容通过setPixmap方法显示到label中

编写快捷终端显示界面

第一步
在main_window.h文件中包含头文件QProcess。
第二步ui设计
放置两个Text Edit一个用来终端命令的输入一个用来输出终端信息。放置几个label用来给用户提示说明。放置一个Line Edit用来给用户选择命令。放置两个按钮,一个用来点击执行终端命令,一个用来确定自己选择的命令。此外在下面可以放置一些按钮用来提供快捷的命令提示。
第三步
使用Qprocess新建对象quck_cmd,使用quick_cmd->start(“bash”)来开启终端。使用quick_cmd->write(ui.textEdit_cmd->toPlainText().toLocal8Bit()+’\n’)来执行命令。在此注意每次点击执行终端命令后把两个Text Edit里的文本内容清空。随后使用connect将终端执行命令后的正确信息和错误信息一起输出到第二个文本框中。

编写rviz基础显示界面

第一步新建一个类
类的名字为qrviz。然后添加依赖项rviz并包含相关头文件。包括rviz下的几个头文件。

1
2
3
4
5
#include <rviz/visualization_manager.h>
#include <rviz/render_panel.h>
#include <rviz/display.h>
#include <rviz/tool_manager.h>
#include <rviz/tool.h>

第二步ui设计
在界面中放置一个Tree Widget用来显示rviz的控件。随后在main_window.cpp中设置treeWidget为两列并隐藏头部。利用new QtreeWidgetItem()添加treeWidget的每一行的第一列,利用new QComboBox()创建ComboBox。利用addItem为ComboBox添加选项。利用setItemWidget把ComboBox添加为tree Widget的第二列。
第三步
在qrviz类的构造函数中创建一个rviz的显示容器并把该容器添加到刚刚放置的纵向布局的界面中。随后创建一个rviz的控制对象并初始化Camera实现放大缩小的功能。然后初始化rviz控制对象。
第四步
设置参考坐标系,在treeWidget界面上添加一行的第一列为参考坐标系,第二列放一个ComboBox用来供用户选择。在此关闭下拉框防止闪退,当连接到master后在使能下拉框。为下拉框设置几个基本的选项比如base_link,map,odom等。创建一个connect,当收到ComboBox里的文本改变信号时执行槽函数slot_treewidget_value_change(QString)。这个槽函数会把ComboBox里的文本内容作为参数值给Set_FixedFrame(QString Frame_name)函数。该函数可以把rviz控制对象的固定坐标系设置为文本设置的坐标系。
第五步添加图层。
按照上述方法添加ui界面后创建图层函数Display* createDisplay(const Qstring& class_lookup_name, const Qstring& name, bool enabled);其中class_lookup_name代表图层类名比如“rviz/Grid”,“rviz/RobotModel”,”rviz/Map”,”rviz/LaserScan”等等。最后设置图层属性函数比如颜色,线条尺寸等,通过subProp(Qstring prop_name)->setValue(Qvariant value)设置。通过以上办法可以将rviz显示的图层界面添加进来显示

编写rviz初始状态估计

第一步放置一个按钮
文本显示为初始状态估计,并添加图标。
第二步
在main_window.cpp中创建一个connect,当收到按钮的点击信号时执行槽函数slot_set_start_pose(),该槽函数会执行函数Set_Start_Pose(),该函数会生成一个初始状态估计的rviz工具对象,并把该对象设置为当前使用的rviz工具。

编写rviz单点导航

放置一个按钮,文本显示为单点导航,并添加图标。在main_window.cpp中创建一个connect,当收到按钮的点击信号时执行槽函数slot_set_goal_pose(),该槽函数会执行函数Set_Goal_Pose(),该函数会生成一个设置目标点的rviz工具对象,并获取该对象的属性容器,通过属性容器发布导航目标点的话题/move_base_simple/goal。随后把该对象设置为当前使用的rviz工具。

编写rviz设置返航点

第一步放置一个按钮
文本显示为设置返航点,并添加图标。放置六个label用来显示当前amcl估计的坐标和返航点坐标。
第二步
在qnode.cpp中订阅amcl_pose话题,一旦收到该话题的内容执行amcl_pose_callback回调函数。该回调函数会把amcl_pose话题里的位置信息提取出来并发送信号position(double x,double y,double z)。 在main_window.cpp中创建一个connect,当收到该信号时执行槽函数slot_update_pos(double,double,double),该槽函数会把信号携带的位置信息显示到label上。
第三步
在main_window.cpp中创建一个connect,当收到按钮的点击信号时执行槽函数slot_set_return_pos(),该槽函数会把label上显示的amcl估计的当前坐标显示到下面一行返航点的label上。

编写rviz开始返航

第一步放置一个按钮
文本显示为开始返航,并添加图标。
第二步
在qnode.cpp中创建发布器发布move_base_simple/goal话题,随后编写函数set_goal(double x,double y,double z) 用来发布目标点。第三步在main_window.cpp中创建一个connect,当收到按钮的点击信号时执行槽函数slot_return(),该槽函数会调用set_goal(double x,double y,double z)把ui界面上的返航点坐标的label上的值作为参数值传给该函数,该函数会调用发布器发布目标点的坐标。

工作空间的CMakeLists.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# toplevel CMakeLists.txt for a catkin workspace
# catkin/cmake/toplevel.cmake

cmake_minimum_required(VERSION 3.0.2)

project(Project)

set(CATKIN_TOPLEVEL TRUE)

# search for catkin within the workspace
set(_cmd "catkin_find_pkg" "catkin" "${CMAKE_SOURCE_DIR}")
execute_process(COMMAND ${_cmd}
RESULT_VARIABLE _res
OUTPUT_VARIABLE _out
ERROR_VARIABLE _err
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_STRIP_TRAILING_WHITESPACE
)
if(NOT _res EQUAL 0 AND NOT _res EQUAL 2)
# searching fot catkin resulted in an error
string(REPLACE ";" " " _cmd_str "${_cmd}")
message(FATAL_ERROR "Search for 'catkin' in workspace failed (${_cmd_str}): ${_err}")
endif()

# include catkin from workspace or via find_package()
if(_res EQUAL 0)
set(catkin_EXTRAS_DIR "${CMAKE_SOURCE_DIR}/${_out}/cmake")
# include all.cmake without add_subdirectory to let it operate in same scope
include(${catkin_EXTRAS_DIR}/all.cmake NO_POLICY_SCOPE)
add_subdirectory("${_out}")

else()
# use either CMAKE_PREFIX_PATH explicitly passed to CMake as a command line argument
# or CMAKE_PREFIX_PATH from the environment
if(NOT DEFINED CMAKE_PREFIX_PATH)
if(NOT "$ENV{CMAKE_PREFIX_PATH}" STREQUAL "")
if(NOT WIN32)
string(REPLACE ":" ";" CMAKE_PREFIX_PATH $ENV{CMAKE_PREFIX_PATH})
else()
set(CMAKE_PREFIX_PATH $ENV{CMAKE_PREFIX_PATH})
endif()
endif()
endif()

# list of catkin workspaces
set(catkin_search_path "")
foreach(path ${CMAKE_PREFIX_PATH})
if(EXISTS "${path}/.catkin")
list(FIND catkin_search_path ${path} _index)
if(_index EQUAL -1)
list(APPEND catkin_search_path ${path})
endif()
endif()
endforeach()

# search for catkin in all workspaces
set(CATKIN_TOPLEVEL_FIND_PACKAGE TRUE)
find_package(catkin QUIET
NO_POLICY_SCOPE
PATHS ${catkin_search_path}
NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
unset(CATKIN_TOPLEVEL_FIND_PACKAGE)

if(NOT catkin_FOUND)
message(FATAL_ERROR "find_package(catkin) failed. catkin was neither found in the workspace nor in the CMAKE_PREFIX_PATH. One reason may be that no ROS setup.sh was sourced before.")
endif()
endif()

catkin_workspace()


功能包下的CMakeLists.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
##############################################################################
# CMake
##############################################################################

cmake_minimum_required(VERSION 2.8.0)
project(qt_ros_test)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
##############################################################################
# Catkin
##############################################################################

# qt_build provides the qt cmake glue, roscpp the comms for a default talker
## find_package(catkin REQUIRED COMPONENTS qt_build rviz roscpp)
find_package(catkin REQUIRED COMPONENTS qt_build rviz roscpp sensor_msgs
cv_bridge
std_msgs
image_transport
)
include_directories(${catkin_INCLUDE_DIRS})
find_package(Qt5 REQUIRED Core Widgets)
set(QT_LIBRARIES Qt5::Widgets)
# Use this to define what the package will export (e.g. libs, headers).
# Since the default here is to produce only a binary, we don't worry about
# exporting anything.
catkin_package()

##############################################################################
# Qt Environment
##############################################################################

# this comes from qt_build's qt-ros.cmake which is automatically
# included via the dependency call in package.xml
# rosbuild_prepare_qt4(QtCore QtGui) # Add the appropriate components to the component list here

##############################################################################
# Sections
##############################################################################

file(GLOB QT_FORMS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ui/*.ui)
file(GLOB QT_RESOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} resources/*.qrc)
file(GLOB_RECURSE QT_MOC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} FOLLOW_SYMLINKS include/qt_ros_test/*.hpp)

QT5_ADD_RESOURCES(QT_RESOURCES_CPP ${QT_RESOURCES})
QT5_WRAP_UI(QT_FORMS_HPP ${QT_FORMS})
QT5_WRAP_CPP(QT_MOC_HPP ${QT_MOC})

##############################################################################
# Sources
##############################################################################

file(GLOB_RECURSE QT_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} FOLLOW_SYMLINKS src/*.cpp)

##############################################################################
# Binaries
##############################################################################

add_executable(qt_ros_test ${QT_SOURCES} ${QT_RESOURCES_CPP} ${QT_FORMS_HPP} ${QT_MOC_HPP})
target_link_libraries(qt_ros_test ${QT_LIBRARIES} ${catkin_LIBRARIES})
install(TARGETS qt_ros_test RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION})



功能包里的src下的cpp
CCtrlDashBoard.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
#include "../include/qt_ros_test/CCtrlDashBoard.hpp"
#include <QPainter>
#include <QDebug>
#include <qmath.h>

CCtrlDashBoard::CCtrlDashBoard(QWidget *parent, StyleType type) :
QWidget(parent),
m_StyleType(type)
{
m_BorderColor = QColor(172,172,172);
m_BgColor = QColor(40,40,40);
m_FrontColor = Qt::white;

m_DashValue= 0;
m_MinValue = 0;
m_MaxValue = 100;
m_DashNum = 1;
m_LineLength=0;

m_StartAngle=90; //510
m_EndAngle=0; //120
update();
}

void CCtrlDashBoard::drawBackGround(QPainter *painter, qreal hlafWidth)
{
m_MaxBorderRadius = ((hlafWidth*5)/6);
qreal startX=hlafWidth-m_MaxBorderRadius;
painter->save();
painter->setPen(m_BorderColor);
painter->setBrush(m_BorderColor);

QPainterPath bigCircle;
bigCircle.addEllipse(startX, startX, (m_MaxBorderRadius*2), (m_MaxBorderRadius*2));

m_MinBorderRadius = m_MaxBorderRadius-15;
startX=hlafWidth-m_MinBorderRadius;
QPainterPath smallCircle;
smallCircle.addEllipse(startX, startX, (m_MinBorderRadius*2), (m_MinBorderRadius*2));

QPainterPath path = bigCircle - smallCircle;
painter->drawPath(path);
painter->restore();

painter->save();
painter->setBrush(m_BgColor);
painter->drawEllipse(startX,startX,(m_MinBorderRadius*2), (m_MinBorderRadius*2));
if(m_DashValue==0){
QString speed = "0.0 cm/s";
painter->drawText(startX+85,startX+170,speed);
}
else{
QString speed = QString::number(m_DashValue).mid(0,3) + " cm/s";
painter->drawText(startX+85,startX+170,speed);
}
painter->restore();
m_DialsRadius = m_MinBorderRadius-10;
if(m_DialsRadius < 0){
m_DialsRadius=2;
}
}
void CCtrlDashBoard::drawScaleDials(QPainter *painter, qreal hlafWidth)
{
qreal tSteps = (m_MaxValue - m_MinValue)/m_DashNum; //相乘后的值是分的份数
qreal angleStep = 1.0*(360.0-m_StartAngle - m_EndAngle) / tSteps; //每一个份数的角度
QPen pen ;
pen.setColor(m_FrontColor); //推荐使用第二种方式
painter->save();
painter->translate(hlafWidth,hlafWidth);
painter->rotate(m_StartAngle);
m_LineLength = (hlafWidth/16);
qreal lineStart = m_DialsRadius-4*m_LineLength-m_LineLength;
qreal lineSmStart = m_DialsRadius-4*m_LineLength-m_LineLength/2;
qreal lineEnd = m_DialsRadius-4*m_LineLength;
for (int i = 0; i <= tSteps; i++)
{
if(i>80) pen.setColor(QColor(250,0,0));
if (i % 10 == 0)//整数刻度显示加粗
{
pen.setWidth(2); //设置线宽
painter->setPen(pen); //使用面向对象的思想,把画笔关联上画家。通过画家画出来
painter->drawLine(lineStart,lineStart, lineEnd, lineEnd); //两个参数应该是两个坐标值
//painter->drawText(lineEnd+6,lineEnd+6, tr("%1").arg(m_MinValue+i));
}
else
{
pen.setWidth(1);
painter->setPen(pen);
painter->drawLine(lineSmStart, lineSmStart, lineEnd, lineEnd); //两个参数应该是两个坐标值
}
painter->rotate(angleStep);
}
pen.setColor(m_FrontColor);
painter->restore();
painter->save();
painter->setPen(pen);
//m_startAngle是起始角度,m_endAngle是结束角度,m_scaleMajor在一个量程中分成的刻度数
qreal startRad = ( 315-m_StartAngle) * (3.14 / 180);
qreal deltaRad = (360-m_StartAngle - m_EndAngle) * (3.14 / 180) / tSteps;
qreal sina,cosa;
qreal x, y;
QFontMetricsF fm(this->font());
double w, h, tmpVal;
QString str;
painter->translate(hlafWidth,hlafWidth);
lineEnd = m_MinBorderRadius-8;
for (int i = 0; i <= tSteps; i++)
{
if (i % 10 == 0)//整数刻度显示加粗
{
sina = qSin(startRad - i * deltaRad);
cosa = cos(startRad - i * deltaRad);

tmpVal = 1.0 * i *((m_MaxValue - m_MinValue) / tSteps) + m_MinValue;
str = QString( "%1" ).arg(tmpVal); //%1作为占位符 arg()函数比起 sprintf()来是类型安全的
w = fm.size(Qt::TextSingleLine,str).width();
h = fm.size(Qt::TextSingleLine,str).height();
x = lineEnd * cosa - w / 2;
y = -lineEnd * sina + h / 4;
painter->drawText(x, y, str); //函数的前两个参数是显示的坐标位置,后一个是显示的内容,是字符类型""
}
}
painter->restore();
}

void CCtrlDashBoard::drawIndicator(QPainter *painter, qreal hlafWidth)
{
QPolygon pts;
pts.setPoints(3, -8,0, 8,0, 0,(int)m_DialsRadius-20); /* (-2,0)/(2,0)/(0,60) *///第一个参数是 ,坐标的个数。后边的是坐标
painter->save();
painter->translate(hlafWidth, hlafWidth);
painter->rotate(m_StartAngle-45);

if(m_DashValue>0){
qreal tSteps = (m_MaxValue - m_MinValue)/m_DashNum; //相乘后的值是分的份数
qreal angleStep = 1.0*(360.0-m_StartAngle - m_EndAngle) / tSteps; //每一个份数的角度
double degRotate = angleStep*tSteps*(m_DashValue/100.0)+angleStep;

//画指针
//qDebug() <<"degRotate =="<<degRotate<<"m_DashValue =="<<m_DashValue<<m_StartAngle<<m_DialsRadius<<hlafWidth;
if(m_DashValue == 99){
painter->rotate(m_EndAngle-m_StartAngle); //顺时针旋转坐标系统
}else
{
painter->rotate(degRotate); //顺时针旋转坐标系统
}

}
QRadialGradient haloGradient(0, 0, hlafWidth/2, 0, 0); //辐射渐变
haloGradient.setColorAt(0, QColor(255,69,0));
haloGradient.setColorAt(1, QColor(255,0,0));
painter->setPen(Qt::white); //定义线条文本颜色 设置线条的颜色
painter->setBrush(haloGradient);//刷子定义形状如何填满 填充后的颜色
painter->drawConvexPolygon(pts); //这是个重载函数,绘制多边形。
painter->restore();

//画中心点
QColor niceBlue(150, 150, 200);
QConicalGradient coneGradient(0, 0, -90.0); //角度渐变
coneGradient.setColorAt(0.0, Qt::darkGray);
coneGradient.setColorAt(0.2, niceBlue);
coneGradient.setColorAt(0.5, Qt::white);
coneGradient.setColorAt(1.0, Qt::darkGray);
painter->save();
painter->translate(hlafWidth,hlafWidth);
painter->setPen(Qt::NoPen); //没有线,填满没有边界
painter->setBrush(coneGradient);
painter->drawEllipse(-10, -10, 20, 20);
painter->restore();
}

void CCtrlDashBoard::drawIndicatorBar(QPainter *painter, qreal hlafWidth)
{
// 渐变色
painter->save();
painter->translate(hlafWidth,hlafWidth);
qreal lineEnd = m_DialsRadius-3*m_LineLength;
QRadialGradient gradient(0, 0, lineEnd);
gradient.setColorAt(0, Qt::white);
gradient.setColorAt(1.0, Qt::blue);
painter->setBrush(gradient);

// << 1(左移1位)相当于radius*2 即:150*2=300
//QRectF(-150, -150, 300, 300)
QRectF rect(-lineEnd, -lineEnd, lineEnd*2, lineEnd*2);
QPainterPath path;
path.arcTo(rect, m_StartAngle, 270);

// QRectF(-120, -120, 240, 240)
QPainterPath subPath;
subPath.addEllipse(rect.adjusted(10, 10, -10, -10));

// path为扇形 subPath为椭圆
path -= subPath;
painter->setPen(Qt::NoPen);
painter->rotate(m_StartAngle+45);
painter->drawPath(path);
painter->restore();


qreal degRotate=0.1;
if(m_DashValue>0){
qreal tSteps = (m_MaxValue - m_MinValue)/m_DashNum; //相乘后的值是分的份数
qreal angleStep = 1.0*(360.0-m_StartAngle - m_EndAngle) / tSteps; //每一个份数的角度
degRotate = angleStep*tSteps*(m_DashValue/100.0)+angleStep;

//画指针
//qDebug() <<"degRotate =="<<degRotate<<"m_DashValue =="<<m_DashValue<<m_StartAngle<<m_DialsRadius<<hlafWidth;
/*if(m_DashValue == 99){
painter->rotate(m_EndAngle-m_StartAngle); //顺时针旋转坐标系统
}else
{
painter->rotate(degRotate); //顺时针旋转坐标系统
}*/
}

painter->save();
painter->translate(hlafWidth, hlafWidth);

QRadialGradient ftGradient(0, 0, lineEnd);
ftGradient.setColorAt(0, Qt::white);
ftGradient.setColorAt(1.0, Qt::darkYellow);
painter->setBrush(ftGradient);

// << 1(左移1位)相当于radius*2 即:150*2=300
//QRectF(-150, -150, 300, 300)
QRectF ftRect(-lineEnd, -lineEnd, lineEnd*2, lineEnd*2);
QPainterPath ftPath;
ftPath.arcTo(ftRect, m_EndAngle-m_StartAngle, -degRotate);
// path为扇形 subPath为椭圆
ftPath -= subPath;
painter->rotate(m_StartAngle-45);
painter->drawPath(ftPath);
painter->restore();

QPolygon pts;
int pointLength=lineEnd-12;
pts.setPoints(3, -6,pointLength-10, 6,pointLength-10, 0,pointLength);
painter->save();
painter->translate(hlafWidth, hlafWidth);
painter->rotate(m_StartAngle-45);

if(m_DashValue == 99){
painter->rotate(m_EndAngle-m_StartAngle); //顺时针旋转坐标系统
}else
{
painter->rotate(degRotate); //顺时针旋转坐标系统
}
painter->setPen(Qt::white); //定义线条文本颜色 设置线条的颜色
painter->setBrush(Qt::blue);//刷子定义形状如何填满 填充后的颜色
painter->drawConvexPolygon(pts); //这是个重载函数,绘制多边形。
painter->restore();
}

void CCtrlDashBoard::paintEvent(QPaintEvent * event)
{
QPainter p(this);
qreal width = qMin((this->width()>>1), (this->height()>>1));

p.setRenderHints(QPainter::Antialiasing|QPainter::TextAntialiasing);

drawBackGround(&p, width);

drawScaleDials(&p, width);
switch(m_StyleType)
{
case ST_DEFAULT:
drawIndicator(&p, width);
break;
case ST_ARCBAR:
drawIndicatorBar(&p, width);
break;
}
}


main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
* @file /src/main.cpp
*
* @brief Qt based gui.
*
* @date November 2010
**/
/*****************************************************************************
** Includes
*****************************************************************************/

#include <QtGui>
#include <QApplication>
#include "../include/qt_ros_test/main_window.hpp"


/*****************************************************************************
** Main
*****************************************************************************/

int main(int argc, char **argv) {

/*********************
** Qt
**********************/
QApplication app(argc, argv);
qt_ros_test::MainWindow w(argc,argv);

w.show();
app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit()));
int result = app.exec();

return result;
}


main_window.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
/**
* @file /src/main_window.cpp
*
* @brief Implementation for the qt gui.
*
* @date February 2011
**/
/*****************************************************************************
** Includes
*****************************************************************************/

#include <QtGui>
#include <QMessageBox>
#include <iostream>
#include <QDebug>
#include "../include/qt_ros_test/main_window.hpp"

/*****************************************************************************
** Namespaces
*****************************************************************************/

namespace qt_ros_test {

using namespace Qt;

/*****************************************************************************
** Implementation [MainWindow]
*****************************************************************************/

MainWindow::MainWindow(int argc, char** argv, QWidget *parent)
: QMainWindow(parent)
, qnode(argc,argv)
{
ui.setupUi(this); // Calling this incidentally connects all ui's triggers to on_...() callbacks in this class.
this->loadStyleSheet("://images/myStyleSheet1.qss");
QObject::connect(ui.actionAbout_Qt, SIGNAL(triggered(bool)), qApp, SLOT(aboutQt())); // qApp is a global variable for the application


ReadSettings();
setWindowIcon(QIcon("://images/icon1.png"));
ui.tab_manager->setCurrentIndex(0); // ensure the first tab is showing - qt-designer should have this already hardwired, but often loses it (settings?).
QObject::connect(&qnode, SIGNAL(rosShutdown()), this, SLOT(close()));

/*********************
** Logging
**********************/
ui.view_logging->setModel(qnode.loggingModel());
QObject::connect(&qnode, SIGNAL(loggingUpdated()), this, SLOT(updateLoggingView()));
/*********************
** Auto Start
**********************/
if ( ui.checkbox_remember_settings->isChecked() ) {
on_button_connect_clicked(true);
}
connect(ui.horizontalSlider_linera,SIGNAL(valueChanged(int)),this,SLOT(slot_linera_change(int)));
connect(ui.horizontalSlider_raw,SIGNAL(valueChanged(int)),this,SLOT(slot_raw_change(int)));
connect(ui.pushButton_u,SIGNAL(clicked()),this,SLOT(slot_pushbtn_click()));
connect(ui.pushButton_i,SIGNAL(clicked()),this,SLOT(slot_pushbtn_click()));
connect(ui.pushButton_o,SIGNAL(clicked()),this,SLOT(slot_pushbtn_click()));
connect(ui.pushButton_j,SIGNAL(clicked()),this,SLOT(slot_pushbtn_click()));
connect(ui.pushButton_l,SIGNAL(clicked()),this,SLOT(slot_pushbtn_click()));
connect(ui.pushButton_m,SIGNAL(clicked()),this,SLOT(slot_pushbtn_click()));
connect(ui.pushButton_1,SIGNAL(clicked()),this,SLOT(slot_pushbtn_click()));
connect(ui.pushButton_2,SIGNAL(clicked()),this,SLOT(slot_pushbtn_click()));
//init ui
speed_x_dashBoard=new CCtrlDashBoard(ui.widget_speed_x);
speed_y_dashBoard=new CCtrlDashBoard(ui.widget_speed_y);
speed_x_dashBoard->setGeometry(ui.widget_speed_x->rect());
speed_y_dashBoard->setGeometry(ui.widget_speed_y->rect());
speed_x_dashBoard->setValue(0);
speed_y_dashBoard->setValue(0);
ui.horizontalSlider_linera->setValue(20);
ui.horizontalSlider_raw->setValue(20);
//header
ui.treeWidget->setHeaderLabels(QStringList()<<"功能"<<"选项");
ui.treeWidget->setHeaderHidden(true);
//GLobal Options
QTreeWidgetItem* Global=new QTreeWidgetItem(QStringList()<<"Global Options");
Global->setIcon(0,QIcon("://images/options.png"));
ui.treeWidget->addTopLevelItem(Global);
Global->setExpanded(true);
//FixFrame
QTreeWidgetItem* Fixed_frame=new QTreeWidgetItem(QStringList()<<"参考坐标系");
fixed_box=new QComboBox();
fixed_box->addItem("map");
// 关闭下拉框防止闪退
fixed_box->setEnabled(false);
fixed_box->addItem("base_link");
fixed_box->addItem("base_laser_link");
fixed_box->addItem("base_footprint");
fixed_box->addItem("odom");
fixed_box->setMaximumWidth(150);
fixed_box->setEditable(true);
connect(fixed_box,SIGNAL(currentTextChanged(QString)),this,SLOT(slot_treewidget_value_change(QString)));
Global->addChild(Fixed_frame);
ui.treeWidget->setItemWidget(Fixed_frame,1,fixed_box);
//Grid
QTreeWidgetItem* Grid=new QTreeWidgetItem(QStringList()<<"图层/栅格");
//设置图标
Grid->setIcon(0,QIcon("://images/'grid.png'"));
//checkbox
Grid_Check=new QCheckBox();
Grid_Check->setEnabled(false);
connect(Grid_Check,SIGNAL(stateChanged(int)),this,SLOT(slot_display_grid(int)));
//添加top节点
ui.treeWidget->addTopLevelItem(Grid);
//添加checkbox
ui.treeWidget->setItemWidget(Grid,1,Grid_Check);
//设置grid默认展开状态
Grid->setExpanded(true);

//添加Cell Count子节点
QTreeWidgetItem* Cell_Count=new QTreeWidgetItem(QStringList()<<"栅格个数");
Grid->addChild(Cell_Count);
//CellCount添加SpinBox
Cell_Count_Box=new QSpinBox();
Cell_Count_Box->setValue(7);
//设置Spinbox的宽度
Cell_Count_Box->setMaximumWidth(150);
ui.treeWidget->setItemWidget(Cell_Count,1,Cell_Count_Box);

//添加color子节点
QTreeWidgetItem* Grid_Color=new QTreeWidgetItem(QStringList()<<"栅格颜色");
Grid->addChild(Grid_Color);
//Color添加ComboBox
Grid_Color_Box=new QComboBox();
Grid_Color_Box->addItem("0;160;160");
//设置Comboox可编辑
Grid_Color_Box->setEditable(true);
//设置Combox的宽度
Grid_Color_Box->setMaximumWidth(150);
ui.treeWidget->setItemWidget(Grid_Color,1,Grid_Color_Box);
//TF ui
QTreeWidgetItem* TF=new QTreeWidgetItem(QStringList()<<"图层/TF");
//设置图标
TF->setIcon(0,QIcon("://images/moverotate.svg"));
//checkbox
TF_Check=new QCheckBox();
TF_Check->setEnabled(false);
connect(TF_Check,SIGNAL(stateChanged(int)),this,SLOT(slot_display_tf(int)));
//向Treewidget添加TF Top节点
ui.treeWidget->addTopLevelItem(TF);
//向TF添加checkbox
ui.treeWidget->setItemWidget(TF,1,TF_Check);
//LaserScan ui
QTreeWidgetItem* LaserScan=new QTreeWidgetItem(QStringList()<<"图层/雷达");
//设置图标
LaserScan->setIcon(0,QIcon("://images/default_class_icon.png"));
//checkbox
Laser_Check=new QCheckBox();
Laser_Check->setEnabled(false);
connect(Laser_Check,SIGNAL(stateChanged(int)),this,SLOT(slot_display_laser(int)));
//向Treewidget添加laserscan Top节点
ui.treeWidget->addTopLevelItem(LaserScan);
//向laserscan添加checkbox
ui.treeWidget->setItemWidget(LaserScan,1,Laser_Check);
//laser topic
QTreeWidgetItem* LaserTopic=new QTreeWidgetItem(QStringList()<<"订阅话题");
Laser_Topic_box=new QComboBox();
Laser_Topic_box->addItem("/scan");
Laser_Topic_box->setEditable(true);
Laser_Topic_box->setMaximumWidth(150);
LaserScan->addChild(LaserTopic);
ui.treeWidget->setItemWidget(LaserTopic,1,Laser_Topic_box);

//RobotModel ui
QTreeWidgetItem* RobotModel=new QTreeWidgetItem(QStringList()<<"图层/机器人模型");
//设置图标
RobotModel->setIcon(0,QIcon("://images/robot.png"));
//checkbox
RobotModel_Check=new QCheckBox();
RobotModel_Check->setEnabled(false);
connect(RobotModel_Check,SIGNAL(stateChanged(int)),this,SLOT(slot_display_RobotModel(int)));
//向Treewidget添加TF Top节点
ui.treeWidget->addTopLevelItem(RobotModel);
//向TF添加checkbox
ui.treeWidget->setItemWidget(RobotModel,1,RobotModel_Check);
//Map ui
QTreeWidgetItem* Map=new QTreeWidgetItem(QStringList()<<"图层/地图");
//设置图标
Map->setIcon(0,QIcon("://images/crosshair.svg"));
//checkbox
Map_Check=new QCheckBox();
Map_Check->setEnabled(false);
connect(Map_Check,SIGNAL(stateChanged(int)),this,SLOT(slot_display_Map(int)));
//向Treewidget添加Map Top节点
ui.treeWidget->addTopLevelItem(Map);
//向Map添加checkbox
ui.treeWidget->setItemWidget(Map,1,Map_Check);
//Map topic
QTreeWidgetItem* MapTopic=new QTreeWidgetItem(QStringList()<<"订阅话题");
Map_Topic_box=new QComboBox();
Map_Topic_box->addItem("/map");
Map_Topic_box->setEditable(true);
Map_Topic_box->setMaximumWidth(150);
Map->addChild(MapTopic);
ui.treeWidget->setItemWidget(MapTopic,1,Map_Topic_box);
//Map color scheme
QTreeWidgetItem* MapColorScheme=new QTreeWidgetItem(QStringList()<<"地图样式");
Map_Color_Scheme_box=new QComboBox();
Map_Color_Scheme_box->addItem("map");
Map_Color_Scheme_box->addItem("costmap");
Map_Color_Scheme_box->addItem("raw");
Map_Color_Scheme_box->setMaximumWidth(150);
Map->addChild(MapColorScheme);
ui.treeWidget->setItemWidget(MapColorScheme,1,Map_Color_Scheme_box);
//Path ui
QTreeWidgetItem* Path=new QTreeWidgetItem(QStringList()<<"图层/路径");
//设置图标
Path->setIcon(0,QIcon("://images/move1d.svg"));
//checkbox
Path_Check=new QCheckBox();
Path_Check->setEnabled(false);
connect(Path_Check,SIGNAL(stateChanged(int)),this,SLOT(slot_display_Path(int)));
//向Treewidget添加Path Top节点
ui.treeWidget->addTopLevelItem(Path);
//向Path添加checkbox
ui.treeWidget->setItemWidget(Path,1,Path_Check);
//Path topic
QTreeWidgetItem* PathTopic=new QTreeWidgetItem(QStringList()<<"订阅话题");
Path_Topic_box=new QComboBox();
Path_Topic_box->addItem("/move_base/GlobalPlanner/plan");
Path_Topic_box->addItem("/move_base/TebLocalPlannerROS/global_plan");
Path_Topic_box->addItem("/move_base/TebLocalPlannerROS/local_plan");
Path_Topic_box->addItem("/move_base/DWAPlannerROS/local_plan");
Path_Topic_box->addItem("/move_base/DWAPlannerROS/global_plan");
Path_Topic_box->setEditable(true);
Path_Topic_box->setMaximumWidth(300);
Path->addChild(PathTopic);
ui.treeWidget->setItemWidget(PathTopic,1,Path_Topic_box);
//Path color scheme
QTreeWidgetItem* PathColorScheme=new QTreeWidgetItem(QStringList()<<"路径颜色");
Path_Color_box=new QComboBox();
Path_Color_box->addItem("0;12;255");
Path_Color_box->setEditable(true);
Path_Color_box->setMaximumWidth(150);
Path->addChild(PathColorScheme);
ui.treeWidget->setItemWidget(PathColorScheme,1,Path_Color_box);
//导航treeWidget
//header
ui.treeWidget_2->setHeaderLabels(QStringList()<<"功能"<<"选项");
// TreeWidget 自动列宽
ui.treeWidget_2->header()->setSectionResizeMode(QHeaderView::ResizeToContents);

ui.treeWidget_2->setHeaderHidden(true);
//GLobal Options
QTreeWidgetItem* na=new QTreeWidgetItem(QStringList()<<"导航显示");
na->setIcon(0,QIcon("://images/options.png"));
ui.treeWidget_2->addTopLevelItem(na);
na->setExpanded(true);
//*******机器人Navigate 相关UI********************************
//Golabal Map***************************************
QTreeWidgetItem* GlobalMap=new QTreeWidgetItem(QStringList()<<"全局地图");
GlobalMap->setIcon(0,QIcon("://images/crosshair.svg"));
GlobalMap_Check=new QCheckBox();
GlobalMap_Check->setEnabled(false);
connect(GlobalMap_Check,SIGNAL(stateChanged(int)),this,SLOT(slot_display_global_map(int)));
ui.treeWidget_2->addTopLevelItem(GlobalMap);
ui.treeWidget_2->setItemWidget(GlobalMap,1,GlobalMap_Check);
GlobalMap->setExpanded(true);


//Global CostMap
QTreeWidgetItem* Global_CostMap=new QTreeWidgetItem(QStringList()<<"全局代价地图");
//设置图标
Global_CostMap->setIcon(0,QIcon("://images/classes/Map.png"));
//Global Map添加子节点
GlobalMap->addChild(Global_CostMap);
//Map topic
QTreeWidgetItem* Global_CostMap_Topic=new QTreeWidgetItem(QStringList()<<"订阅话题");
Global_CostMap_Topic_box=new QComboBox();
Global_CostMap_Topic_box->addItem("/move_base/global_costmap/costmap");

Global_CostMap_Topic_box->setEditable(true);
Global_CostMap_Topic_box->setMaximumWidth(300);
Global_CostMap->addChild(Global_CostMap_Topic);
ui.treeWidget_2->setItemWidget(Global_CostMap_Topic,1,Global_CostMap_Topic_box);
//Map color scheme
QTreeWidgetItem* GlobalMapColorScheme=new QTreeWidgetItem(QStringList()<<"地图样式");
GlobalMapColorScheme_box=new QComboBox();
GlobalMapColorScheme_box->addItem("map");
GlobalMapColorScheme_box->addItem("costmap");
GlobalMapColorScheme_box->addItem("raw");
GlobalMapColorScheme_box->setMaximumWidth(150);
Global_CostMap->addChild(GlobalMapColorScheme);
ui.treeWidget_2->setItemWidget(GlobalMapColorScheme,1,GlobalMapColorScheme_box);

//Global Planner
QTreeWidgetItem* Global_Planner=new QTreeWidgetItem(QStringList()<<"全局路径");
//设置图标
Global_Planner->setIcon(0,QIcon("://images/classes/Path.png"));
//向TGlobal Map添加Path Top节点
GlobalMap->addChild(Global_Planner);

//Path topic
QTreeWidgetItem* Global_Planner_Topic=new QTreeWidgetItem(QStringList()<<"订阅话题");
Global_Planner_Topic_box=new QComboBox();
Global_Planner_Topic_box->addItem("/move_base/TebLocalPlannerROS/global_plan");
Global_Planner_Topic_box->addItem("/move_base/DWAPlannerROS/global_plan");
Global_Planner_Topic_box->addItem("/move_base/GlobalPlanner/plan");
Global_Planner_Topic_box->setEditable(true);
Global_Planner_Topic_box->setMaximumWidth(300);
Global_Planner->addChild(Global_Planner_Topic);
ui.treeWidget_2->setItemWidget(Global_Planner_Topic,1,Global_Planner_Topic_box);
//Path color scheme
QTreeWidgetItem* Global_Planner_Color_Scheme=new QTreeWidgetItem(QStringList()<<"路径颜色");
Global_Planner_Color_box=new QComboBox();
Global_Planner_Color_box->addItem("255;0;0");
Global_Planner_Color_box->setEditable(true);
Global_Planner_Color_box->setMaximumWidth(150);
Global_Planner->addChild(Global_Planner_Color_Scheme);
ui.treeWidget_2->setItemWidget(Global_Planner_Color_Scheme,1,Global_Planner_Color_box);

//Local Map***********************************************
QTreeWidgetItem* LocalMap=new QTreeWidgetItem(QStringList()<<"局部地图");
LocalMap->setIcon(0,QIcon("://images/crosshair.svg"));
LocalMap_Check=new QCheckBox();
LocalMap_Check->setEnabled(false);
connect(LocalMap_Check,SIGNAL(stateChanged(int)),this,SLOT(slot_display_local_map(int)));
ui.treeWidget_2->addTopLevelItem(LocalMap);
ui.treeWidget_2->setItemWidget(LocalMap,1,LocalMap_Check);
LocalMap->setExpanded(true);
//Local CostMap
QTreeWidgetItem* Local_CostMap=new QTreeWidgetItem(QStringList()<<"局部代价地图");
//设置图标
Local_CostMap->setIcon(0,QIcon("://images/classes/Map.png"));
//Local Map添加子节点
LocalMap->addChild(Local_CostMap);
//Map topic
QTreeWidgetItem* Local_CostMap_Topic=new QTreeWidgetItem(QStringList()<<"订阅话题");
Local_CostMap_Topic_box=new QComboBox();
Local_CostMap_Topic_box->addItem("/move_base/local_costmap/costmap");
Local_CostMap_Topic_box->setEditable(true);
Local_CostMap_Topic_box->setMaximumWidth(300);
Local_CostMap->addChild(Local_CostMap_Topic);
ui.treeWidget_2->setItemWidget(Local_CostMap_Topic,1,Local_CostMap_Topic_box);
//Map color scheme
QTreeWidgetItem* LocalMapColorScheme=new QTreeWidgetItem(QStringList()<<"地图样式");
LocalMapColorScheme_box=new QComboBox();
LocalMapColorScheme_box->addItem("costmap");
LocalMapColorScheme_box->addItem("map");
LocalMapColorScheme_box->addItem("raw");
LocalMapColorScheme_box->setMaximumWidth(150);
Local_CostMap->addChild(LocalMapColorScheme);
ui.treeWidget_2->setItemWidget(LocalMapColorScheme,1,LocalMapColorScheme_box);

//Local Planner
QTreeWidgetItem* Local_Planner=new QTreeWidgetItem(QStringList()<<"局部路径");
//设置图标
Local_Planner->setIcon(0,QIcon("://images/classes/Path.png"));
//向TLocal Map添加Path Top节点
LocalMap->addChild(Local_Planner);

//Path topic
QTreeWidgetItem* Local_Planner_Topic=new QTreeWidgetItem(QStringList()<<"订阅话题");
Local_Planner_Topic_box=new QComboBox();
Local_Planner_Topic_box->addItem("/move_base/TebLocalPlannerROS/local_plan");
Local_Planner_Topic_box->addItem("/move_base/DWAPlannerROS/local_plan");
Local_Planner_Topic_box->setEditable(true);
Local_Planner_Topic_box->setMaximumWidth(300);
Local_Planner->addChild(Local_Planner_Topic);
ui.treeWidget_2->setItemWidget(Local_Planner_Topic,1,Local_Planner_Topic_box);
//Path color scheme
QTreeWidgetItem* Local_Planner_Color_Scheme=new QTreeWidgetItem(QStringList()<<"路径颜色");
Local_Planner_Color_box=new QComboBox();
Local_Planner_Color_box->addItem("0;12;255");
Local_Planner_Color_box->setEditable(true);
Local_Planner_Color_box->setMaximumWidth(150);
Local_Planner->addChild(Local_Planner_Color_Scheme);
ui.treeWidget_2->setItemWidget(Local_Planner_Color_Scheme,1,Local_Planner_Color_box);
//**********************************************************************************************
connect(&qnode,SIGNAL(speed_vel(float,float)),this,SLOT(slot_update_dashboard(float,float)));
connect(&qnode,SIGNAL(power_vel(float)),this,SLOT(slot_update_power(float)));
connect(&qnode,SIGNAL(image_val(QImage)),this,SLOT(slot_update_image(QImage)));
connect(ui.pushButton_sub_image,SIGNAL(clicked()),this,SLOT(slot_sub_image()));
connect(&qnode,SIGNAL(position(double,double,double)),this,SLOT(slot_update_pos(double,double,double)));
//set start and goal pose
connect(ui.set_start_btn,SIGNAL(clicked()),this,SLOT(slot_set_start_pose()));
connect(ui.set_goal_btn,SIGNAL(clicked()),this,SLOT(slot_set_goal_pose()));
// set return pose
connect(ui.set_return_pos_btn,SIGNAL(clicked()),this,SLOT(slot_set_return_pos()));
connect(ui.return_btn,SIGNAL(clicked()),this,SLOT(slot_return()));
//cmd
connect(ui.cmd_btn,SIGNAL(clicked()),this,SLOT(slot_cmd_clicked()));
connect(ui.cmd_home,SIGNAL(clicked()),this,SLOT(slot_cmd_home_clicked()));
connect(ui.cmd_pei,SIGNAL(clicked()),this,SLOT(slot_cmd_pei_clicked()));
connect(ui.cmd_message,SIGNAL(clicked()),this,SLOT(slot_cmd_message_clicked()));
connect(ui.cmd_topic,SIGNAL(clicked()),this,SLOT(slot_cmd_topic_clicked()));
connect(ui.cmd_topic_content,SIGNAL(clicked()),this,SLOT(slot_cmd_topic_content_clicked()));
connect(ui.cmd_pubtopic,SIGNAL(clicked()),this,SLOT(slot_cmd_pubtopic_clicked()));
connect(ui.cmd_node,SIGNAL(clicked()),this,SLOT(slot_cmd_node_clicked()));
connect(ui.cmd_plot,SIGNAL(clicked()),this,SLOT(slot_cmd_plot_clicked()));
connect(ui.cmd_slam,SIGNAL(clicked()),this,SLOT(slot_cmd_slam_clicked()));
connect(ui.cmd_saver_map,SIGNAL(clicked()),this,SLOT(slot_cmd_saver_map_clicked()));
connect(ui.cmd_pub_map,SIGNAL(clicked()),this,SLOT(slot_cmd_pub_map_clicked()));
connect(ui.cmd_amcl,SIGNAL(clicked()),this,SLOT(slot_cmd_amcl_clicked()));
connect(ui.cmd_choose,SIGNAL(clicked()),this,SLOT(slot_cmd_choose_clicked()));
connect(ui.cmd_hector,SIGNAL(clicked()),this,SLOT(slot_cmd_hector_clicked()));
connect(ui.cmd_cartographer,SIGNAL(clicked()),this,SLOT(slot_cmd_cartographer_clicked()));
connect(ui.cmd_dijkstra_teb,SIGNAL(clicked()),this,SLOT(slot_cmd_dijkstra_teb_clicked()));
connect(ui.cmd_dijkstra_DWA,SIGNAL(clicked()),this,SLOT(slot_cmd_dijkstra_DWA_clicked()));
connect(ui.cmd_A_teb,SIGNAL(clicked()),this,SLOT(slot_cmd_A_teb_clicked()));
connect(ui.cmd_A_DWA,SIGNAL(clicked()),this,SLOT(slot_cmd_A_DWA_clicked()));
}
//***********cmd*****
void MainWindow::slot_cmd_choose_clicked()
{
if(cmd_saver_map_flag==1)
{
ui.textEdit_cmd->append("rosrun map_server map_saver -f " + ui.lineEdit_cmd->text());
cmd_saver_map_flag=0;
ui.lineEdit_cmd->clear();
}
if(cmd_pub_map_flag==1)
{
ui.textEdit_cmd->append("rosrun map_server map_server " + ui.lineEdit_cmd->text());
cmd_pub_map_flag=0;
ui.lineEdit_cmd->clear();
}
if(cmd_amcl_flag==1)
{
ui.textEdit_cmd->append("roslaunch " + ui.lineEdit_cmd->text());
cmd_amcl_flag=0;
ui.lineEdit_cmd->clear();
}
if(cmd_slam_flag==1)
{
ui.textEdit_cmd->append("roslaunch " + ui.lineEdit_cmd->text());
cmd_slam_flag=0;
ui.lineEdit_cmd->clear();
}
if(cmd_hector_flag==1)
{
ui.textEdit_cmd->append("roslaunch " + ui.lineEdit_cmd->text());
cmd_hector_flag=0;
ui.lineEdit_cmd->clear();
}

if(cmd_cartographer_flag==1)
{
ui.textEdit_cmd->append("roslaunch " + ui.lineEdit_cmd->text());
cmd_cartographer_flag=0;
ui.lineEdit_cmd->clear();
}
if(cmd_dijkstra_teb_flag==1)
{
ui.textEdit_cmd->append("roslaunch " + ui.lineEdit_cmd->text());
cmd_dijkstra_teb_flag=0;
ui.lineEdit_cmd->clear();
}

if(cmd_dijkstra_DWA_flag==1)
{
ui.textEdit_cmd->append("roslaunch " + ui.lineEdit_cmd->text());
cmd_dijkstra_DWA_flag=0;
ui.lineEdit_cmd->clear();
}
if(cmd_A_teb_flag==1)
{
ui.textEdit_cmd->append("roslaunch " + ui.lineEdit_cmd->text());
cmd_A_teb_flag=0;
ui.lineEdit_cmd->clear();
}
if(cmd_A_DWA_flag==1)
{
ui.textEdit_cmd->append("roslaunch " + ui.lineEdit_cmd->text());
cmd_A_DWA_flag=0;
ui.lineEdit_cmd->clear();
}
}
void MainWindow::slot_cmd_A_DWA_clicked()
{
ui.textEdit_quick_output->append("robot_navigation move_base.launch use_dijkstra:=false planner:=dwa");
cmd_A_DWA_flag=1;
}
void MainWindow::slot_cmd_A_teb_clicked()
{
ui.textEdit_quick_output->append("robot_navigation move_base.launch use_dijkstra:=false planner:=teb");
cmd_A_teb_flag=1;
}
void MainWindow::slot_cmd_dijkstra_DWA_clicked()
{
ui.textEdit_quick_output->append("robot_navigation move_base.launch planner:=dwa");
cmd_dijkstra_DWA_flag=1;
}
void MainWindow::slot_cmd_dijkstra_teb_clicked()
{
ui.textEdit_quick_output->append("robot_navigation move_base.launch planner:=teb");
cmd_dijkstra_teb_flag=1;
}
void MainWindow::slot_cmd_cartographer_clicked()
{
ui.textEdit_quick_output->append("请先进行以下操作");
ui.textEdit_quick_output->append("安装cartographer:https://blog.csdn.net/wxc_1998/article/details/122802419");
ui.textEdit_quick_output->append("roscd cartographer_ros");
ui.textEdit_quick_output->append("找到这个包里的configuration_files文件夹里的revo_lds.lua复制内容");
ui.textEdit_quick_output->append("新建 config文件夹和revo_lds.lua文件粘贴内容并修改");
ui.textEdit_quick_output->append("tracking_frame更改为我们机器人的基坐标tf,一般是base_footprint");
ui.textEdit_quick_output->append("odom_frame更改为odom");
ui.textEdit_quick_output->append("按照map->odom_frame->publisher_frame->tracking_frame");
ui.textEdit_quick_output->append("published_frame更改为odom");
ui.textEdit_quick_output->append("use_odometry更改为true");
ui.textEdit_quick_output->append("provide_odom_frame更改为false");
ui.textEdit_quick_output->append("odometry_sampling_ratio更改为0.1");

ui.textEdit_quick_output->append("roscd cartographer_ros");
ui.textEdit_quick_output->append("找到这个包里的launch文件夹里的demo_revo_lds.launch复制内容");
ui.textEdit_quick_output->append("新建 launch 文件粘贴内容并修改");
ui.textEdit_quick_output->append("更改下面的configuration_directory为刚刚配置文件的包和目录");
ui.textEdit_quick_output->append("更改下面的configuration_basename为刚刚配置文件的名字");
ui.textEdit_quick_output->append("<remap from=\"scan\" to=\"scan\"/>");
ui.textEdit_quick_output->append("<remap from=\"odom\" to=\"odom\"/>");
ui.textEdit_quick_output->append("删除倒数第一个第二个node标签");
ui.textEdit_quick_output->append("<node pkg=\"joint_state_publisher\" name=\"joint_state_publisher\" type=\"joint_state_publisher\" />");
ui.textEdit_quick_output->append("<node pkg=\"robot_state_publisher\" name=\"robot_state_publisher\" type=\"robot_state_publisher\" />");
ui.textEdit_quick_output->append("最后两个在整个程序中必须被启动,否则无法正确显示机器人模型");
ui.textEdit_quick_output->append("然后输入你编写cartographer建图启动的launch文件所在的功能包名和launch文件名比如");
ui.textEdit_quick_output->append("nav_demo nav03_slam.launch ");
cmd_hector_flag=1;
}
void MainWindow::slot_cmd_hector_clicked()
{
ui.textEdit_quick_output->append("请先进行以下操作");
ui.textEdit_quick_output->append("安装 hector-slam包(用于构建地图):sudo apt install ros-ROS版本-hector-slam");
ui.textEdit_quick_output->append("安装地图服务包(用于保存与读取地图):sudo apt install ros-ROS版本-map-server");
ui.textEdit_quick_output->append("安装 navigation 包(用于定位以及路径规划):sudo apt install ros-ROS版本-navigation");
ui.textEdit_quick_output->append("新建功能包,并导入依赖: hector_slam map_server amcl move_base");
ui.textEdit_quick_output->append("新建 launch 文件");
ui.textEdit_quick_output->append("复制 https://www.guyuehome.com/42755 launch 文件内容");
ui.textEdit_quick_output->append("删除第二个第三个node标签");
ui.textEdit_quick_output->append("做如下修改和添加");
ui.textEdit_quick_output->append("<param name=\"base_frame\" value=\"base_footprint\"/>");
ui.textEdit_quick_output->append("<param name=\"odom_frame\" value=\"odom\"/>");
ui.textEdit_quick_output->append("<node pkg=\"joint_state_publisher\" name=\"joint_state_publisher\" type=\"joint_state_publisher\" />");
ui.textEdit_quick_output->append("<node pkg=\"robot_state_publisher\" name=\"robot_state_publisher\" type=\"robot_state_publisher\" />");
ui.textEdit_quick_output->append("最后两个在整个程序中必须被启动,否则无法正确显示机器人模型");
ui.textEdit_quick_output->append("然后输入你编写hector建图启动的launch文件所在的功能包名和launch文件名比如");
ui.textEdit_quick_output->append("nav_demo nav02_slam.launch ");
cmd_hector_flag =1;
}
void MainWindow::slot_cmd_slam_clicked()
{
ui.textEdit_quick_output->append("请先进行以下操作");
ui.textEdit_quick_output->append("安装 gmapping包(用于构建地图):sudo apt install ros-ROS版本-gmapping");
ui.textEdit_quick_output->append("安装地图服务包(用于保存与读取地图):sudo apt install ros-ROS版本-map-server");
ui.textEdit_quick_output->append("安装 navigation 包(用于定位以及路径规划):sudo apt install ros-ROS版本-navigation");
ui.textEdit_quick_output->append("新建功能包,并导入依赖: gmapping map_server amcl move_base");
ui.textEdit_quick_output->append("新建 launch 文件");
ui.textEdit_quick_output->append("复制 https://github.com/ros-perception/slam_gmapping/blob/melodic-devel/gmapping/launch/slam_gmapping_pr2.launch 文件内容");
ui.textEdit_quick_output->append("编写新的launch文件做如下修改和添加");
ui.textEdit_quick_output->append("<remap from=\"scan\" to=\"scan\"/>");
ui.textEdit_quick_output->append("<param name=\"base_frame\" value=\"base_footprint\"/>");
ui.textEdit_quick_output->append("<param name=\"odom_frame\" value=\"odom\"/>");
ui.textEdit_quick_output->append("<node pkg=\"joint_state_publisher\" name=\"joint_state_publisher\" type=\"joint_state_publisher\" />");
ui.textEdit_quick_output->append("<node pkg=\"robot_state_publisher\" name=\"robot_state_publisher\" type=\"robot_state_publisher\" />");
ui.textEdit_quick_output->append("最后两个在整个程序中必须被启动,否则无法正确显示机器人模型");
ui.textEdit_quick_output->append("然后输入你编写gmapping建图启动的launch文件所在的功能包名和launch文件名比如");
ui.textEdit_quick_output->append("nav_demo nav01_slam.launch ");
cmd_slam_flag=1;
}
void MainWindow::slot_cmd_amcl_clicked()
{
ui.textEdit_quick_output->append("请先进行以下操作");
ui.textEdit_quick_output->append("sudo apt install ros-ROS版本-navigation");
ui.textEdit_quick_output->append("新建功能包,并导入依赖: amcl move_base");
ui.textEdit_quick_output->append("执行roscd amcl 和ls examples ,新建 launch 文件,复制 amcl_diff.launch 文件内容编写新的launch文件");
ui.textEdit_quick_output->append("在<param name=\"odom_frame_id\" value=\"odom\"/>下添加");
ui.textEdit_quick_output->append("<param name=\"base_frame_id\" value=\"base_footprint\"/>");
ui.textEdit_quick_output->append("<param name=\"global_frame_id\" value=\"map\"/>");
ui.textEdit_quick_output->append("完成后请确保你已经启动发布地图,机器人模型");
ui.textEdit_quick_output->append("然后输入你编写amcl启动的launch文件所在的功能包名和launch文件名比如");
ui.textEdit_quick_output->append("nav_demo amcl.launch");
cmd_amcl_flag=1;

}
void MainWindow::slot_cmd_pub_map_clicked()
{
ui.textEdit_quick_output->append("请在选择框输入后点击确定");
ui.textEdit_quick_output->append("请输入你要发布地图的地址,比如");
ui.textEdit_quick_output->append("~/catkin_ws/src/map/my_map.yaml");
cmd_pub_map_flag=1;
}
void MainWindow::slot_cmd_saver_map_clicked()
{
ui.textEdit_quick_output->append("请在选择框输入后点击确定");
ui.textEdit_quick_output->append("请输入你要保存地图的地址,比如");
ui.textEdit_quick_output->append("~/catkin_ws/src/map/my_map");
cmd_saver_map_flag=1;
}
void MainWindow::slot_cmd_plot_clicked()
{
ui.textEdit_cmd->append("rqt_plot");
}
void MainWindow::slot_cmd_node_clicked()
{
ui.textEdit_cmd->append("rqt_graph");
}
void MainWindow::slot_cmd_pubtopic_clicked()
{
ui.textEdit_cmd->append("rostopic pub /cmd_vel 两次tab");
}
void MainWindow::slot_cmd_topic_content_clicked()
{
ui.textEdit_cmd->append("rostopic echo /cmd_vel");
}
void MainWindow::slot_cmd_topic_clicked()
{
ui.textEdit_cmd->append("rostopic info /cmd_vel");
}
void MainWindow::slot_cmd_message_clicked()
{
ui.textEdit_cmd->append("rosmsg show geometry_msgs/Twist");
}

void MainWindow::slot_cmd_pei_clicked()
{
ui.textEdit_cmd->append("ssh-keygen -t rsa");
ui.textEdit_cmd->append("ssh-copy-id 用户名@远程主机ip");

}
void MainWindow::slot_cmd_home_clicked()
{
ui.textEdit_cmd->append("cd ~");
}
void MainWindow::slot_cmd_clicked()
{
ui.textEdit_quick_output->clear();
quick_cmd=new QProcess;
quick_cmd->start("bash");
quick_cmd->write(ui.textEdit_cmd->toPlainText().toLocal8Bit()+'\n');
ui.textEdit_cmd->clear();

connect(quick_cmd,SIGNAL(readyReadStandardOutput()),this,SLOT(slot_quick_output()));
connect(quick_cmd,SIGNAL(readyReadStandardError()),this,SLOT(slot_quick_output()));
}
void MainWindow::slot_quick_output()
{
ui.textEdit_quick_output->append("<font color=\"#FF000000\">"+quick_cmd->readAllStandardOutput()+"</font>");
ui.textEdit_quick_output->append("<font color=\"#FF0000\">"+quick_cmd->readAllStandardError()+"</font>");
}
//***************
void MainWindow::slot_set_return_pos()
{
ui.return_x->setText(ui.pos_x->text());
ui.return_y->setText(ui.pos_y->text());
ui.return_z->setText(ui.pos_z->text());
}
void MainWindow::slot_return()
{
qnode.set_goal(ui.return_x->text().toDouble(),ui.return_y->text().toDouble(),ui.return_z->text().toDouble());
}
void MainWindow::slot_update_pos(double x,double y,double z)
{
ui.pos_x->setText(QString::number(x));
ui.pos_y->setText(QString::number(y));
ui.pos_z->setText(QString::number(z));
}
void MainWindow::slot_display_local_map(int state)
{
bool enable=state>1?true:false;
QStringList qli=Local_Planner_Color_box->currentText().split(";");
QColor color=QColor(qli[0].toInt(),qli[1].toInt(),qli[2].toInt());
myrviz->Display_Local_Map(Local_CostMap_Topic_box->currentText(),LocalMapColorScheme_box->currentText(),Local_Planner_Topic_box->currentText(),color,enable);
}
void MainWindow::slot_display_global_map(int state)
{
bool enable=state>1?true:false;
QStringList qli=Global_Planner_Color_box->currentText().split(";");
QColor color=QColor(qli[0].toInt(),qli[1].toInt(),qli[2].toInt());
myrviz->Display_Global_Map(Global_CostMap_Topic_box->currentText(),GlobalMapColorScheme_box->currentText(),Global_Planner_Topic_box->currentText(),color,enable);
}
void MainWindow::slot_set_start_pose()
{
myrviz->Set_Start_Pose();
}
void MainWindow::slot_set_goal_pose()
{
myrviz->Set_Goal_Pose();
}
void MainWindow::slot_display_Path(int state)
{
bool enable=state>1?true:false;
QStringList qli=Path_Color_box->currentText().split(";");
QColor color=QColor(qli[0].toInt(),qli[1].toInt(),qli[2].toInt());
myrviz->Display_Path(Path_Topic_box->currentText(),color,enable);
qDebug()<<Path_Topic_box->currentText();
}
void MainWindow::slot_display_Map(int state)
{
bool enable=state>1?true:false;
myrviz->Display_Map(Map_Topic_box->currentText(),Map_Color_Scheme_box->currentText(),enable);
}
void MainWindow::slot_display_RobotModel(int state)
{
bool enable=state>1?true:false;
myrviz->Display_RobotModel(enable);
}
void MainWindow::slot_display_laser(int state)
{
bool enable=state>1?true:false;
myrviz->Display_LaserScan(Laser_Topic_box->currentText(),enable);
}
void MainWindow::slot_display_tf(int state)
{
bool enable=state>1?true:false;
myrviz->Display_TF(enable);
}
void MainWindow::slot_display_grid(int state)
{
bool enable=state>1?true:false;
QStringList qli=Grid_Color_Box->currentText().split(";");
QColor color=QColor(qli[0].toInt(),qli[1].toInt(),qli[2].toInt());
myrviz->Display_Grid(Cell_Count_Box->text().toInt(),color,enable);
}
void MainWindow::slot_treewidget_value_change(QString)
{
myrviz->Set_FixedFrame(fixed_box->currentText());
}
void MainWindow::slot_update_image(QImage im)
{
ui.label_image->setPixmap(QPixmap::fromImage(im));
}
void MainWindow::slot_sub_image()
{
qnode.sub_image(ui.lineEdit_image_topic->text());
}
void MainWindow::slot_update_power(float value)
{
ui.label_power_val->setText(QString::number(value).mid(0,5)+"V");
double n=(value-9.6)/(11.7-9.6);
int val=n*100;
ui.progressBar->setValue(val);


}
void MainWindow::slot_update_dashboard(float x,float y)
{ ui.label_dir_x->setText(x>0?"正向":"反向");
ui.label_dir_y->setText(y>0?"正向":"反向");
speed_x_dashBoard->setValue(abs(x)*100);
speed_y_dashBoard->setValue(abs(y)*100);
}
void MainWindow::slot_linera_change(int value)

{
ui.label_linera->setText(QString::number(value));
}
void MainWindow::slot_raw_change(int value)

{
ui.label_raw->setText(QString::number(value));
}
void MainWindow::slot_pushbtn_click()

{
QPushButton* btn =qobject_cast<QPushButton*>(sender());
//qDebug() <<btn->text();
char k=btn->text().toStdString()[0];
bool is_all=ui.checkBox_is_all->isChecked();
float linear=ui.label_linera->text().toFloat()*0.01;
float angular=ui.label_raw->text().toFloat()*0.01;
switch (k) {
case 'i':
qnode.set_cmd_vel(is_all?'I':'i',linear,angular);
break;
case 'u':
qnode.set_cmd_vel(is_all?'U':'u',linear,angular);
break;
case 'o':
qnode.set_cmd_vel(is_all?'O':'o',linear,angular);
break;
case 'j':
qnode.set_cmd_vel(is_all?'J':'j',linear,angular);
break;
case 'l':
qnode.set_cmd_vel(is_all?'L':'l',linear,angular);
break;
case 'm':
qnode.set_cmd_vel(is_all?'M':'m',linear,angular);
break;
case ',':
qnode.set_cmd_vel(is_all?'<':',',linear,angular);
break;
case '.':
qnode.set_cmd_vel(is_all?'>':'.',linear,angular);
break;
}
}
MainWindow::~MainWindow() {}

/*****************************************************************************
** Implementation [Slots]
*****************************************************************************/

void MainWindow::showNoMasterMessage() {
QMessageBox msgBox;
msgBox.setText("Couldn't find the ros master.");
msgBox.exec();
close();
}

/*
* These triggers whenever the button is clicked, regardless of whether it
* is already checked or not.
*/

void MainWindow::on_button_connect_clicked(bool check ) {
if ( ui.checkbox_use_environment->isChecked() ) {
if ( !qnode.init() ) {
showNoMasterMessage();
fixed_box->setEnabled(false);

ui.pushButton_sub_image->setEnabled(false);
ui.treeWidget->setEnabled(false);

} else {
ui.button_connect->setEnabled(false);
ui.pushButton_sub_image->setEnabled(true);
ui.treeWidget->setEnabled(true);
fixed_box->setEnabled(true);
Grid_Check->setEnabled(true);
TF_Check->setEnabled(true);
Laser_Check->setEnabled(true);
RobotModel_Check->setEnabled(true);
Map_Check->setEnabled(true);
Path_Check->setEnabled(true);
GlobalMap_Check->setEnabled(true);
LocalMap_Check->setEnabled(true);
ui.pushButton_u->setEnabled(true);
ui.pushButton_i->setEnabled(true);
ui.pushButton_o->setEnabled(true);
ui.pushButton_j->setEnabled(true);
ui.pushButton_l->setEnabled(true);
ui.pushButton_m->setEnabled(true);
ui.pushButton_1->setEnabled(true);
ui.pushButton_2->setEnabled(true);
ui.set_goal_btn->setEnabled(true);
ui.set_start_btn->setEnabled(true);
ui.set_return_pos_btn->setEnabled(true);
ui.return_btn->setEnabled(true);
myrviz=new qrviz(ui.layout_rviz);
}
} else {
if ( ! qnode.init(ui.line_edit_master->text().toStdString(),
ui.line_edit_host->text().toStdString()) ) {
showNoMasterMessage();
ui.pushButton_sub_image->setEnabled(false);
ui.treeWidget->setEnabled(false);
fixed_box->setEnabled(false);
} else {
ui.button_connect->setEnabled(false);
ui.line_edit_master->setReadOnly(true);
ui.line_edit_host->setReadOnly(true);
ui.line_edit_topic->setReadOnly(true);
ui.pushButton_sub_image->setEnabled(true);
ui.treeWidget->setEnabled(true);
fixed_box->setEnabled(true);
Grid_Check->setEnabled(true);
TF_Check->setEnabled(true);
Laser_Check->setEnabled(true);
RobotModel_Check->setEnabled(true);
Map_Check->setEnabled(true);
Path_Check->setEnabled(true);
GlobalMap_Check->setEnabled(true);
LocalMap_Check->setEnabled(true);
ui.pushButton_u->setEnabled(true);
ui.pushButton_i->setEnabled(true);
ui.pushButton_o->setEnabled(true);
ui.pushButton_j->setEnabled(true);
ui.pushButton_l->setEnabled(true);
ui.pushButton_m->setEnabled(true);
ui.pushButton_1->setEnabled(true);
ui.pushButton_2->setEnabled(true);
ui.set_goal_btn->setEnabled(true);
ui.set_start_btn->setEnabled(true);
ui.set_return_pos_btn->setEnabled(true);
ui.return_btn->setEnabled(true);
myrviz=new qrviz(ui.layout_rviz);
}
}
}


void MainWindow::on_checkbox_use_environment_stateChanged(int state) {
bool enabled;
if ( state == 0 ) {
enabled = true;
} else {
enabled = false;
}
ui.line_edit_master->setEnabled(enabled);
ui.line_edit_host->setEnabled(enabled);
//ui.line_edit_topic->setEnabled(enabled);
}

/*****************************************************************************
** Implemenation [Slots][manually connected]
*****************************************************************************/

/**
* This function is signalled by the underlying model. When the model changes,
* this will drop the cursor down to the last line in the QListview to ensure
* the user can always see the latest log message.
*/
void MainWindow::updateLoggingView() {
ui.view_logging->scrollToBottom();
}

/*****************************************************************************
** Implementation [Menu]
*****************************************************************************/

void MainWindow::on_actionAbout_triggered() {
QMessageBox::about(this, tr("About ..."),tr("<h2>PACKAGE_NAME Test Program 0.10</h2><p>Copyright Yujin Robot</p><p>This package needs an about description.</p>"));
}

/*****************************************************************************
** Implementation [Configuration]
*****************************************************************************/

void MainWindow::ReadSettings() {
QSettings settings("Qt-Ros Package", "qt_ros_test");
restoreGeometry(settings.value("geometry").toByteArray());
restoreState(settings.value("windowState").toByteArray());
QString master_url = settings.value("master_url",QString("http://192.168.1.2:11311/")).toString();
QString host_url = settings.value("host_url", QString("192.168.1.3")).toString();
//QString topic_name = settings.value("topic_name", QString("/chatter")).toString();
ui.line_edit_master->setText(master_url);
ui.line_edit_host->setText(host_url);
//ui.line_edit_topic->setText(topic_name);
bool remember = settings.value("remember_settings", false).toBool();
ui.checkbox_remember_settings->setChecked(remember);
bool checked = settings.value("use_environment_variables", false).toBool();
ui.checkbox_use_environment->setChecked(checked);
if ( checked ) {
ui.line_edit_master->setEnabled(false);
ui.line_edit_host->setEnabled(false);
//ui.line_edit_topic->setEnabled(false);
}
}

void MainWindow::WriteSettings() {
QSettings settings("Qt-Ros Package", "qt_ros_test");
settings.setValue("master_url",ui.line_edit_master->text());
settings.setValue("host_url",ui.line_edit_host->text());
//settings.setValue("topic_name",ui.line_edit_topic->text());
settings.setValue("use_environment_variables",QVariant(ui.checkbox_use_environment->isChecked()));
settings.setValue("geometry", saveGeometry());
settings.setValue("windowState", saveState());
settings.setValue("remember_settings",QVariant(ui.checkbox_remember_settings->isChecked()));

}

void MainWindow::loadStyleSheet(const QString &styleSheetFile)
{
QFile file(styleSheetFile);
file.open(QFile::ReadOnly);
if (file.isOpen())
{
QString styleSheet = this->styleSheet();
styleSheet += QLatin1String(file.readAll());//读取样式表文件
this->setStyleSheet(styleSheet);//把文件内容传参
file.close();
}
else
{
QMessageBox::information(this,"tip","cannot find qss file");
}

}
void MainWindow::closeEvent(QCloseEvent *event)
{
WriteSettings();
QMainWindow::closeEvent(event);
}

} // namespace qt_ros_test



void qt_ros_test::MainWindow::on_btn_theme_1_clicked()
{

}


qnode.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
/**
* @file /src/qnode.cpp
*
* @brief Ros communication central!
*
* @date February 2011
**/

/*****************************************************************************
** Includes
*****************************************************************************/

#include <ros/ros.h>
#include <ros/network.h>
#include <string>
#include <std_msgs/String.h>
#include <sstream>
#include "../include/qt_ros_test/qnode.hpp"
/*****************************************************************************
** Namespaces
*****************************************************************************/

namespace qt_ros_test {

/*****************************************************************************
** Implementation
*****************************************************************************/

QNode::QNode(int argc, char** argv ) :
init_argc(argc),
init_argv(argv)
{}

QNode::~QNode() {
if(ros::isStarted()) {
ros::shutdown(); // explicitly needed since we use ros::start();
ros::waitForShutdown();
}
wait();
}

bool QNode::init() {
ros::init(init_argc,init_argv,"qt_ros_test");
if ( ! ros::master::check() ) {
return false;
}
ros::start(); // explicitly needed since our nodehandle is going out of scope.
ros::NodeHandle n;
// Add your ros communications here.
chatter_publisher = n.advertise<std_msgs::String>("chatter", 1000);
cmd_vel_pub = n.advertise<geometry_msgs::Twist>("cmd_vel", 1000);
odom_sub = n.subscribe("odom",1000,&QNode::odom_raw_callback,this);
power_sub = n.subscribe("voltage",1000,&QNode::power_callback,this);
amcl_pose_sub =n.subscribe("amcl_pose",1000,&QNode::amcl_pose_callback,this);
goal_pub=n.advertise<geometry_msgs::PoseStamped>("move_base_simple/goal",1000);
start();
return true;
}

bool QNode::init(const std::string &master_url, const std::string &host_url) {
std::map<std::string,std::string> remappings;
remappings["__master"] = master_url;
remappings["__hostname"] = host_url;
ros::init(remappings,"qt_ros_test");
if ( ! ros::master::check() ) {
return false;
}
ros::start(); // explicitly needed since our nodehandle is going out of scope.
ros::NodeHandle n;
// Add your ros communications here.
chatter_publisher = n.advertise<std_msgs::String>("chatter", 1000);
cmd_vel_pub = n.advertise<geometry_msgs::Twist>("cmd_vel", 1000);
odom_sub = n.subscribe("odom",1000,&QNode::odom_raw_callback,this);
power_sub = n.subscribe("voltage",1000,&QNode::power_callback,this);
amcl_pose_sub =n.subscribe("amcl_pose",1000,&QNode::amcl_pose_callback,this);
goal_pub=n.advertise<geometry_msgs::PoseStamped>("move_base_simple/goal",1000);
start();
return true;
}

void QNode::set_goal(double x,double y,double z)
{
geometry_msgs::PoseStamped goal;
//设置frame
goal.header.frame_id="map";
//设置时刻
goal.header.stamp=ros::Time::now();
goal.pose.position.x=x;
goal.pose.position.y=y;
goal.pose.orientation.z=z;
goal_pub.publish(goal);
}
void QNode::amcl_pose_callback(const geometry_msgs::PoseWithCovarianceStamped &msg)
{

emit position(msg.pose.pose.position.x,msg.pose.pose.position.y,msg.pose.pose.orientation.z);
}
void QNode:: sub_image(QString topic_name)
{
ros::NodeHandle n;
image_transport::ImageTransport it_(n);
image_sub=it_.subscribe(topic_name.toStdString(),1000,&QNode::image_callback,this);

}
void QNode::image_callback(const sensor_msgs::ImageConstPtr &msg)
{
cv_bridge::CvImagePtr cv_ptr;
cv_ptr=cv_bridge::toCvCopy(msg,msg->encoding);
QImage im=Mat2QImage(cv_ptr->image);

emit image_val(im);
}
QImage QNode::Mat2QImage(cv::Mat const& src)
{
QImage dest(src.cols, src.rows, QImage::Format_ARGB32);

const float scale = 255.0;

if (src.depth() == CV_8U) {
if (src.channels() == 1) {
for (int i = 0; i < src.rows; ++i) {
for (int j = 0; j < src.cols; ++j) {
int level = src.at<quint8>(i, j);
dest.setPixel(j, i, qRgb(level, level, level));
}
}
} else if (src.channels() == 3) {
for (int i = 0; i < src.rows; ++i) {
for (int j = 0; j < src.cols; ++j) {
cv::Vec3b bgr = src.at<cv::Vec3b>(i, j);
dest.setPixel(j, i, qRgb(bgr[2], bgr[1], bgr[0]));
}
}
}
} else if (src.depth() == CV_32F) {
if (src.channels() == 1) {
for (int i = 0; i < src.rows; ++i) {
for (int j = 0; j < src.cols; ++j) {
int level = scale * src.at<float>(i, j);
dest.setPixel(j, i, qRgb(level, level, level));
}
}
} else if (src.channels() == 3) {
for (int i = 0; i < src.rows; ++i) {
for (int j = 0; j < src.cols; ++j) {
cv::Vec3f bgr = scale * src.at<cv::Vec3f>(i, j);
dest.setPixel(j, i, qRgb(bgr[2], bgr[1], bgr[0]));
}
}
}
}

return dest;
}
void QNode::power_callback(const std_msgs::Float32 &msg)
{
emit power_vel(msg.data);
}
void QNode::odom_raw_callback(const nav_msgs::Odometry &msg)
{
emit speed_vel(msg.twist.twist.linear.x,msg.twist.twist.linear.y);

}

void QNode::set_cmd_vel(char k, float linear, float angular)
{
// Map for movement keys
std::map<char, std::vector<float>> moveBindings
{
{'i', {1, 0, 0, 0}},
{'o', {1, 0, 0, -1}},
{'j', {0, 0, 0, 1}},
{'l', {0, 0, 0, -1}},
{'u', {1, 0, 0, 1}},
{',', {-1, 0, 0, 0}},
{'.', {-1, 0, 0, 1}},
{'m', {-1, 0, 0, -1}},
{'O', {1, -1, 0, 0}},
{'I', {1, 0, 0, 0}},
{'J', {0, 1, 0, 0}},
{'L', {0, -1, 0, 0}},
{'U', {1, 1, 0, 0}},
{'<', {-1, 0, 0, 0}},
{'>', {-1, -1, 0, 0}},
{'M', {-1, 1, 0, 0}},
{'t', {0, 0, 1, 0}},
{'b', {0, 0, -1, 0}},
{'k', {0, 0, 0, 0}},
{'K', {0, 0, 0, 0}}
};
char key=k;
// Grab the direction data
int x = moveBindings[key][0];
int y = moveBindings[key][1];
int z = moveBindings[key][2];
int th = moveBindings[key][3];
geometry_msgs::Twist twist;
twist.linear.x=x*linear;
twist.linear.y=y*linear;
twist.linear.z=z*linear;
twist.angular.x=0;
twist.angular.y=0;
twist.angular.z=th*angular;
cmd_vel_pub.publish(twist);
}
void QNode::run() {
ros::Rate loop_rate(1);
int count = 0;
while ( ros::ok() ) {

std_msgs::String msg;
std::stringstream ss;
ss << "hello world " << count;
msg.data = ss.str();
chatter_publisher.publish(msg);
log(Info,std::string("I sent: ")+msg.data);
ros::spinOnce();
loop_rate.sleep();
++count;
}
std::cout << "Ros shutdown, proceeding to close the gui." << std::endl;
Q_EMIT rosShutdown(); // used to signal the gui for a shutdown (useful to roslaunch)
}


void QNode::log( const LogLevel &level, const std::string &msg) {
logging_model.insertRows(logging_model.rowCount(),1);
std::stringstream logging_model_msg;
switch ( level ) {
case(Debug) : {
ROS_DEBUG_STREAM(msg);
logging_model_msg << "[DEBUG] [" << ros::Time::now() << "]: " << msg;
break;
}
case(Info) : {
ROS_INFO_STREAM(msg);
logging_model_msg << "[INFO] [" << ros::Time::now() << "]: " << msg;
break;
}
case(Warn) : {
ROS_WARN_STREAM(msg);
logging_model_msg << "[INFO] [" << ros::Time::now() << "]: " << msg;
break;
}
case(Error) : {
ROS_ERROR_STREAM(msg);
logging_model_msg << "[ERROR] [" << ros::Time::now() << "]: " << msg;
break;
}
case(Fatal) : {
ROS_FATAL_STREAM(msg);
logging_model_msg << "[FATAL] [" << ros::Time::now() << "]: " << msg;
break;
}
}
QVariant new_row(QString(logging_model_msg.str().c_str()));
logging_model.setData(logging_model.index(logging_model.rowCount()-1),new_row);
Q_EMIT loggingUpdated(); // used to readjust the scrollbar
}

} // namespace qt_ros_test


qrviz.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#include "../include/qt_ros_test/qrviz.hpp"
#include <QDebug>
#include <QException>
qrviz::qrviz(QVBoxLayout* layout)
{

//创建rviz panel
render_panel_=new rviz::RenderPanel();
//向layout添加
layout->addWidget(render_panel_);
//创建rviz控制对象
manager_=new rviz::VisualizationManager(render_panel_);
tool_manager_=manager_->getToolManager();
ROS_ASSERT(manager_!=NULL);
//初始化render_panel 实现放大缩小等操作
render_panel_->initialize(manager_->getSceneManager(),manager_);

manager_->setFixedFrame("map");
//初始化rviz控制对象
manager_->initialize();
manager_->startUpdate();
manager_->removeAllDisplays();

}
void qrviz::Display_Local_Map(QString map_topic,QString map_color,QString planner_topic,QColor planner_color,bool enable)
{
if(Local_Map_!=NULL||Local_Planner_!=NULL)
{
delete Local_Map_;
delete Local_Planner_;
Local_Map_=NULL;
Local_Planner_=NULL;
}
Local_Map_=manager_->createDisplay("rviz/Map","LocalMap",enable);
ROS_ASSERT(Local_Map_!=NULL);
Local_Planner_=manager_->createDisplay("rviz/Path","LocalPlanner",enable);
ROS_ASSERT(Local_Planner_!=NULL);
Local_Map_->subProp("Topic")->setValue(map_topic);
Local_Map_->subProp("Color Scheme")->setValue(map_color);
// Local_Planner_->subProp("Topic")->setValue(planner_topic);
// Local_Planner_->subProp("Color")->setValue(planner_color);


}
void qrviz::Display_Global_Map(QString map_topic,QString map_color,QString planner_topic,QColor planner_color,bool enable)
{
if(Global_Map_!=NULL||Global_Planner_!=NULL)
{
delete Global_Map_;
delete Global_Planner_;
Global_Map_=NULL;
Global_Planner_=NULL;
}
Global_Map_=manager_->createDisplay("rviz/Map","GlobalMap",enable);
ROS_ASSERT(Global_Map_!=NULL);
Global_Planner_=manager_->createDisplay("rviz/Path","GlobalPlanner",enable);
ROS_ASSERT(Global_Planner_!=NULL);
Global_Map_->subProp("Topic")->setValue(map_topic);
Global_Map_->subProp("Color Scheme")->setValue(map_color);
// Global_Planner_->subProp("Topic")->setValue(planner_topic);
// Global_Planner_->subProp("Color")->setValue(planner_color);


}
void qrviz::Set_Start_Pose()
{
rviz::Tool* current_tool_=tool_manager_->addTool("rviz/SetInitialPose");
//设置当前使用的工具
tool_manager_->setCurrentTool(current_tool_);
}
void qrviz::Set_Goal_Pose()
{
rviz::Tool* current_tool_=tool_manager_->addTool("rviz/SetGoal");
//获取属性容器
rviz::Property* pro=current_tool_->getPropertyContainer();
//设置发布导航目标点的topic
pro->subProp("Topic")->setValue("/move_base_simple/goal");
//设置当前使用的工具
tool_manager_->setCurrentTool(current_tool_);
}
void qrviz::Set_FixedFrame(QString Frame_name)
{
manager_->setFixedFrame(Frame_name);
qDebug()<<manager_->getFixedFrame();
}
void qrviz::Display_Grid(int Cell_Count,QColor color,bool enable)
{
if(Grid_!=NULL)
{
delete Grid_;
Grid_=NULL;
}
Grid_=manager_->createDisplay("rviz/Grid","myGrid",enable);
//设置cell Count
Grid_->subProp("Plane Cell Count")->setValue(Cell_Count);
//设置颜色
Grid_->subProp("Color")->setValue(color);
ROS_ASSERT(Grid_!=NULL);

}
void qrviz::Display_TF(bool enable)
{
if(TF_!=NULL)
{
delete TF_;
TF_=NULL;
}
TF_=manager_->createDisplay("rviz/TF","myTF",enable);
ROS_ASSERT(TF_!=NULL);
}
void qrviz::Display_LaserScan(QString laser_topic,bool enable)
{
if(LaserScan_!=NULL)
{
delete LaserScan_;
LaserScan_=NULL;
}
LaserScan_=manager_->createDisplay("rviz/LaserScan","myLaser",enable);
LaserScan_->subProp("Topic")->setValue(laser_topic);
LaserScan_->subProp("Size")->setValue(0.05);
ROS_ASSERT(LaserScan_!=NULL);
}
void qrviz::Display_RobotModel(bool enable)
{
if(RobotModel_!=NULL)
{
delete RobotModel_;
RobotModel_=NULL;
}
RobotModel_=manager_->createDisplay("rviz/RobotModel","myRobotModel",enable);
ROS_ASSERT(RobotModel_!=NULL);
}
void qrviz::Display_Map(QString topic,QString color_scheme,bool enable)
{
if(Map_!=NULL)
{
delete Map_;
Map_=NULL;
}
Map_=manager_->createDisplay("rviz/Map","myMap",enable);
ROS_ASSERT(Map_!=NULL);
Map_->subProp("Topic")->setValue(topic);
Map_->subProp("Color Scheme")->setValue(color_scheme);
}

void qrviz::Display_Path(QString topic,QColor color,bool enable)
{
if(Path_!=NULL)
{
delete Path_;
Path_=NULL;
}
Path_=manager_->createDisplay("rviz/Path","myPath",enable);
ROS_ASSERT(Path_!=NULL);
Path_->subProp("Topic")->setValue(topic);
Path_->subProp("Color")->setValue(color);
}


main_window.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/**
* @file /include/qt_ros_test/main_window.hpp
*
* @brief Qt based gui for qt_ros_test.
*
* @date November 2010
**/
#ifndef qt_ros_test_MAIN_WINDOW_H
#define qt_ros_test_MAIN_WINDOW_H

/*****************************************************************************
** Includes
*****************************************************************************/

#include<QtWidgets/QMainWindow>
#include "ui_main_window.h"
#include "qnode.hpp"
#include "CCtrlDashBoard.hpp"
#include <QImage>
#include <QProcess>
#include <QComboBox>
#include <QSpinBox>
#include "qrviz.hpp"
/*****************************************************************************
** Namespace
*****************************************************************************/

namespace qt_ros_test {

/*****************************************************************************
** Interface [MainWindow]
*****************************************************************************/
/**
* @brief Qt central, all operations relating to the view part here.
*/
class MainWindow : public QMainWindow {
Q_OBJECT

public:
MainWindow(int argc, char** argv, QWidget *parent = 0);
~MainWindow();

void ReadSettings(); // Load up qt program settings at startup
void WriteSettings(); // Save qt program settings when closing

void closeEvent(QCloseEvent *event); // Overloaded function
void showNoMasterMessage();
void loadStyleSheet(const QString &styleSheetFile);


public Q_SLOTS:
/******************************************
** Auto-connections (connectSlotsByName())
*******************************************/
void on_actionAbout_triggered();
void on_button_connect_clicked(bool check );
void on_checkbox_use_environment_stateChanged(int state);

/******************************************
** Manual connections
*******************************************/
void updateLoggingView(); // no idea why this can't connect automatically
void slot_linera_change(int);
void slot_raw_change(int);
void slot_pushbtn_click();
void slot_update_dashboard(float,float);
void slot_update_power(float);
void slot_update_image(QImage);
void slot_sub_image();
void slot_treewidget_value_change(QString);
void slot_display_grid(int);
void slot_display_tf(int);
void slot_display_laser(int);
void slot_display_RobotModel(int);
void slot_display_Map(int);
void slot_display_Path(int);
void slot_set_start_pose();
void slot_set_goal_pose();
void slot_display_local_map(int);
void slot_display_global_map(int);
void slot_update_pos(double,double,double);
void slot_set_return_pos();
void slot_return();
void slot_cmd_clicked();
void slot_quick_output();
void slot_cmd_home_clicked();
void slot_cmd_pei_clicked();
void slot_cmd_message_clicked();
void slot_cmd_topic_clicked();
void slot_cmd_topic_content_clicked();
void slot_cmd_pubtopic_clicked();
void slot_cmd_node_clicked();
void slot_cmd_plot_clicked();
void slot_cmd_saver_map_clicked();
void slot_cmd_choose_clicked();
void slot_cmd_pub_map_clicked();
void slot_cmd_amcl_clicked();
void slot_cmd_slam_clicked();
void slot_cmd_hector_clicked();
void slot_cmd_cartographer_clicked();
void slot_cmd_dijkstra_teb_clicked();
void slot_cmd_dijkstra_DWA_clicked();
void slot_cmd_A_teb_clicked();
void slot_cmd_A_DWA_clicked();
private slots:
void on_btn_theme_1_clicked();

private:
Ui::MainWindowDesign ui;
QNode qnode;
CCtrlDashBoard* speed_x_dashBoard;
CCtrlDashBoard* speed_y_dashBoard;
qrviz* myrviz;
QComboBox* fixed_box;
QCheckBox* Grid_Check;
QSpinBox* Cell_Count_Box;
QComboBox* Grid_Color_Box;
QCheckBox* TF_Check;
QComboBox* Laser_Topic_box;
QCheckBox* Laser_Check;
QCheckBox* RobotModel_Check;
QComboBox* Map_Color_Scheme_box;
QComboBox* Map_Topic_box;
QCheckBox* Map_Check;
QComboBox* Path_Topic_box;
QComboBox* Path_Color_box;
QCheckBox* Path_Check;
QCheckBox* GlobalMap_Check;
QCheckBox* LocalMap_Check;
QComboBox* Global_CostMap_Topic_box;
QComboBox* GlobalMapColorScheme_box;
QComboBox* Global_Planner_Topic_box;
QComboBox* Global_Planner_Color_box;
QComboBox* Local_CostMap_Topic_box;
QComboBox* LocalMapColorScheme_box;
QComboBox* Local_Planner_Topic_box;
QComboBox* Local_Planner_Color_box;
QProcess* quick_cmd;
int cmd_saver_map_flag = 0;
int cmd_slam_flag = 0;
int cmd_pub_map_flag = 0 ;
int cmd_amcl_flag = 0;
int cmd_hector_flag = 0;
int cmd_cartographer_flag = 0;
int cmd_dijkstra_teb_flag = 0;
int cmd_dijkstra_DWA_flag = 0;
int cmd_A_teb_flag = 0;
int cmd_A_DWA_flag = 0;
};

} // namespace qt_ros_test

#endif // qt_ros_test_MAIN_WINDOW_H


qnode.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/**
* @file /include/qt_ros_test/qnode.hpp
*
* @brief Communications central!
*
* @date February 2011
**/
/*****************************************************************************
** Ifdefs
*****************************************************************************/

#ifndef qt_ros_test_QNODE_HPP_
#define qt_ros_test_QNODE_HPP_

/*****************************************************************************
** Includes
*****************************************************************************/

// To workaround boost/qt4 problems that won't be bugfixed. Refer to
// https://bugreports.qt.io/browse/QTBUG-22829
#ifndef Q_MOC_RUN
#include <ros/ros.h>
#endif
#include <string>
#include <QThread>
#include <QStringListModel>
#include <map>
#include <geometry_msgs/Twist.h>
#include <nav_msgs/Odometry.h>
#include <std_msgs/Float32.h>
#include <image_transport/image_transport.h>
#include <cv_bridge/cv_bridge.h>
#include <sensor_msgs/image_encodings.h>
#include <geometry_msgs/PoseWithCovarianceStamped.h>
#include <geometry_msgs/PoseStamped.h>
#include <QImage>
/*****************************************************************************
** Namespaces
*****************************************************************************/

namespace qt_ros_test {

/*****************************************************************************
** Class
*****************************************************************************/

class QNode : public QThread {
Q_OBJECT
public:
QNode(int argc, char** argv );
virtual ~QNode();
bool init();
bool init(const std::string &master_url, const std::string &host_url);
void set_cmd_vel(char k,float linear, float angular);
void sub_image(QString topic_name);
void set_goal(double x,double y,double z);
void run();
/*********************
** Logging
**********************/
enum LogLevel {
Debug,
Info,
Warn,
Error,
Fatal
};

QStringListModel* loggingModel() { return &logging_model; }
void log( const LogLevel &level, const std::string &msg);

Q_SIGNALS:
void loggingUpdated();
void rosShutdown();
void speed_vel(float,float);
void power_vel(float);
void image_val(QImage);
void position(double x,double y,double z);
private:
int init_argc;
char** init_argv;
ros::Publisher chatter_publisher;
ros::Publisher cmd_vel_pub;
ros::Publisher goal_pub;
ros::Subscriber odom_sub;
ros::Subscriber power_sub;
ros::Subscriber amcl_pose_sub;
image_transport::Subscriber image_sub;
QStringListModel logging_model;
void image_callback(const sensor_msgs::ImageConstPtr &msg);
void odom_raw_callback(const nav_msgs::Odometry &msg);
void power_callback(const std_msgs::Float32 &msg);
void amcl_pose_callback(const geometry_msgs::PoseWithCovarianceStamped &msg);
QImage Mat2QImage(cv::Mat const& src);
};

} // namespace qt_ros_test

#endif /* qt_ros_test_QNODE_HPP_ */


qrviz.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#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 <QVBoxLayout>

class qrviz
{
public:
qrviz(QVBoxLayout* layout);
void Set_FixedFrame(QString Frame_name);
void Display_Grid(int Cell_Count,QColor color,bool enable);
void Display_TF(bool enable);
void Display_LaserScan(QString laser_topic,bool enable);
void Display_RobotModel(bool enable);
void Display_Map(QString topic,QString color_scheme, bool enable);
void Display_Path(QString topic,QColor color,bool enable);
void Set_Start_Pose();
void Set_Goal_Pose();
void Display_Local_Map(QString map_topic,QString map_color,QString planner_topic,QColor planner_color,bool enable);
void Display_Global_Map(QString map_topic,QString map_color,QString planner_topic,QColor planner_color,bool enable);
private:
rviz::RenderPanel* render_panel_;
rviz::VisualizationManager* manager_;
rviz::ToolManager* tool_manager_;
rviz::Display* Grid_=NULL;
rviz::Display* TF_=NULL;
rviz::Display* LaserScan_=NULL;
rviz::Display* RobotModel_=NULL;
rviz::Display* Map_=NULL;
rviz::Display* Path_=NULL;
//navigate
rviz::Display* Global_Map_=NULL;
rviz::Display* Global_Planner_=NULL;
rviz::Display* Local_Map_=NULL;
rviz::Display* Local_Planner_=NULL;


};

#endif // QRVIZ_HPP