Procházet zdrojové kódy

feat(tool_fsm_test):add a tool for testing FSM

孙嘉城 před 3 roky
rodič
revize
712bd6cc4c

+ 73 - 0
src/tool/tool_FSM_Test/.gitignore

@@ -0,0 +1,73 @@
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+.directory
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# qtcreator generated files
+*.pro.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+# --------
+*.dll
+*.exe
+

+ 11 - 0
src/tool/tool_FSM_Test/main.cpp

@@ -0,0 +1,11 @@
+#include "mainwindow.h"
+
+#include <QApplication>
+
+int main(int argc, char *argv[])
+{
+    QApplication a(argc, argv);
+    MainWindow w;
+    w.show();
+    return a.exec();
+}

+ 300 - 0
src/tool/tool_FSM_Test/mainwindow.cpp

@@ -0,0 +1,300 @@
+#include "mainwindow.h"
+#include "ui_mainwindow.h"
+
+MainWindow::MainWindow(QWidget *parent)
+    : QMainWindow(parent)
+    , ui(new Ui::MainWindow)
+{
+    ui->setupUi(this);
+
+    std::string strmsgname;
+
+    strmsgname = "brainstate";
+    strncpy(shmBrainState.mstrmsgname,strmsgname.data(),255);
+    shmBrainState.mnBufferSize = 10000;
+    shmBrainState.mnBufferCount = 10;
+
+    strmsgname = "FSMSkipCommand";
+    strncpy(shmFSMSkipCMD.mstrmsgname,strmsgname.data(),255);
+    shmFSMSkipCMD.mnBufferSize = 10000;
+    shmFSMSkipCMD.mnBufferCount = 1;
+
+    shmFSMSkipCMD.mpa = iv::modulecomm::RegisterSend(shmFSMSkipCMD.mstrmsgname,shmFSMSkipCMD.mnBufferSize,shmFSMSkipCMD.mnBufferCount);
+    ModuleFun funupdate = std::bind(&MainWindow::ListenBrainStateMsg,this,std::placeholders::_1,std::placeholders::_2,std::placeholders::_3,std::placeholders::_4,std::placeholders::_5);
+    shmBrainState.mpa = iv::modulecomm::RegisterRecvPlus(shmBrainState.mstrmsgname,funupdate);
+
+    QObject::connect(&signalSendTimer,&QTimer::timeout,this,&MainWindow::signalSend_Timeout);
+    if(signalSendTimer.isActive() == false)signalSendTimer.start(50);
+}
+
+MainWindow::~MainWindow()
+{
+    signalSendTimer.stop();
+    if(shmFSMSkipCMD.mpa != nullptr)iv::modulecomm::Unregister(shmFSMSkipCMD.mpa);
+    if(shmBrainState.mpa != nullptr)iv::modulecomm::Unregister(shmBrainState.mpa);
+    delete ui;
+}
+
+void MainWindow::ListenBrainStateMsg(const char * strdata,const unsigned int nSize,const unsigned int index,const QDateTime * dt,const char * strmemname)
+{
+    iv::brain::brainstate xdata;
+    if(!xdata.ParseFromArray(strdata,nSize))
+    {
+        std::cout<<" ListenBrainStateMsg parese error."<<std::endl;
+        return;
+    }
+
+    FSMState = xdata.mbfsm_state(); //0:待命停车 1:任务中 2:人工接管 3:停工停车 4:返程 5:返库
+
+    switch (FSMState) {
+    case 0:
+        ui->FSMStateTextBrowser->setText("0待命停车");
+        if(missionCMD == iv::brain::MissionCMD::MISSIOH_FINISH \
+                || missionCMD == iv::brain::MissionCMD::MISSION_CANCEL)
+        {
+            missionCMD = iv::brain::MissionCMD::MISSION_RESERVED;
+            ui->missionResButton->setChecked(true);
+        }
+        if(workCMD == iv::brain::WorkCMD::WORK_START)
+        {
+            workCMD = iv::brain::WorkCMD::WORK_RESERVED;
+            ui->workResButton->setChecked(true);
+        }
+        if(remoteCtrlCMD == iv::brain::RemoteCtrlCMD::REMOTE_CTRL_EXIT)
+        {
+            remoteCtrlCMD = iv::brain::RemoteCtrlCMD::REMOTE_CTRL_RESERVED;
+            ui->remoteResButton->setChecked(true);
+        }
+        if(waitingStationArrived == true)
+        {
+            waitingStationArrived = false;
+            ui->waitSta_checkBox->setChecked(false);
+        }
+        break;
+    case 1:
+        ui->FSMStateTextBrowser->setText("1任务中");
+        if(missionCMD == iv::brain::MissionCMD::MISSION_START)
+        {
+            missionCMD = iv::brain::MissionCMD::MISSION_RESERVED;
+            ui->missionResButton->setChecked(true);
+        }
+        if(remoteCtrlCMD == iv::brain::RemoteCtrlCMD::REMOTE_CTRL_EXIT)
+        {
+            remoteCtrlCMD = iv::brain::RemoteCtrlCMD::REMOTE_CTRL_RESERVED;
+            ui->remoteResButton->setChecked(true);
+        }
+        break;
+    case 2:
+        ui->FSMStateTextBrowser->setText("2人工接管");
+        if(remoteCtrlCMD == iv::brain::RemoteCtrlCMD::REMOTE_CTRL_ENTER)
+        {
+            remoteCtrlCMD = iv::brain::RemoteCtrlCMD::REMOTE_CTRL_RESERVED;
+            ui->remoteResButton->setChecked(true);
+        }
+        break;
+    case 3:
+        ui->FSMStateTextBrowser->setText("3停工停车");
+        if(remoteCtrlCMD == iv::brain::RemoteCtrlCMD::REMOTE_CTRL_EXIT)
+        {
+            remoteCtrlCMD = iv::brain::RemoteCtrlCMD::REMOTE_CTRL_RESERVED;
+            ui->remoteResButton->setChecked(true);
+        }
+        if(maintainStationArrived == true)
+        {
+            maintainStationArrived = false;
+            ui->maintainSta_checkBox->setChecked(false);
+        }
+        break;
+    case 4:
+        ui->FSMStateTextBrowser->setText("4返程");
+        if(remoteCtrlCMD == iv::brain::RemoteCtrlCMD::REMOTE_CTRL_EXIT)
+        {
+            remoteCtrlCMD = iv::brain::RemoteCtrlCMD::REMOTE_CTRL_RESERVED;
+            ui->remoteResButton->setChecked(true);
+        }
+        break;
+    case 5:
+        ui->FSMStateTextBrowser->setText("5返库");
+        if(workCMD == iv::brain::WorkCMD::WORK_STOP)
+        {
+            workCMD = iv::brain::WorkCMD::WORK_RESERVED;
+            ui->workResButton->setChecked(true);
+        }
+        if(remoteCtrlCMD == iv::brain::RemoteCtrlCMD::REMOTE_CTRL_EXIT)
+        {
+            remoteCtrlCMD = iv::brain::RemoteCtrlCMD::REMOTE_CTRL_RESERVED;
+            ui->remoteResButton->setChecked(true);
+        }
+        break;
+    default:
+        break;
+    }
+}
+
+void MainWindow::signalSend_Timeout(void)
+{
+    iv::brain::fsm_skip_cmd xmsg;
+    xmsg.set_timestamp(QDateTime::currentMSecsSinceEpoch());
+    xmsg.set_missioncmd(missionCMD);
+    xmsg.set_workcmd(workCMD);
+    xmsg.set_remotectrlcmd(remoteCtrlCMD);
+    xmsg.set_waitingstationarrived(waitingStationArrived);
+    xmsg.set_maintainstationarrived(maintainStationArrived);
+
+    int ndatasize = xmsg.ByteSize();
+    char * str = new char[ndatasize];
+    std::shared_ptr<char> pstr;pstr.reset(str);
+    if(!xmsg.SerializeToArray(str,ndatasize))
+    {
+        std::cout<<"FSMSkipCommand serialize error."<<std::endl;
+        return;
+    }
+    iv::modulecomm::ModuleSendMsg(shmFSMSkipCMD.mpa,str,ndatasize);
+}
+
+void MainWindow::on_missionStaButton_clicked(bool checked)
+{
+    if(checked)
+        missionCMD = iv::brain::MissionCMD::MISSION_START;
+}
+
+void MainWindow::on_missionFinButton_clicked(bool checked)
+{
+    if(checked)
+        missionCMD = iv::brain::MissionCMD::MISSIOH_FINISH;
+}
+
+void MainWindow::on_missionCanButton_clicked(bool checked)
+{
+    if(checked)
+        missionCMD = iv::brain::MissionCMD::MISSION_CANCEL;
+}
+
+void MainWindow::on_workStaButton_clicked(bool checked)
+{
+    if(checked)
+        workCMD = iv::brain::WorkCMD::WORK_START;
+}
+
+void MainWindow::on_workStoButton_clicked(bool checked)
+{
+    if(checked)
+        workCMD = iv::brain::WorkCMD::WORK_STOP;
+}
+
+void MainWindow::on_remoteExiButton_clicked(bool checked)
+{
+    if(checked)
+        remoteCtrlCMD = iv::brain::RemoteCtrlCMD::REMOTE_CTRL_EXIT;
+}
+
+void MainWindow::on_remoteEntButton_clicked(bool checked)
+{
+    if(checked)
+        remoteCtrlCMD = iv::brain::RemoteCtrlCMD::REMOTE_CTRL_ENTER;
+}
+
+void MainWindow::on_waitSta_checkBox_clicked(bool checked)
+{
+    if(checked)
+        waitingStationArrived = true;
+    else
+        waitingStationArrived = false;
+}
+
+void MainWindow::on_maintainSta_checkBox_clicked(bool checked)
+{
+    if(checked)
+        maintainStationArrived = true;
+    else
+        maintainStationArrived = false;
+}
+
+void MainWindow::on_comboBox_activated(int index)
+{
+    FSMState = index; //0:待命停车 1:任务中 2:人工接管 3:停工停车 4:返程 5:返库
+
+    switch (FSMState) {
+    case 0:
+        ui->FSMStateTextBrowser->setText("0待命停车");
+        if(missionCMD == iv::brain::MissionCMD::MISSIOH_FINISH \
+                || missionCMD == iv::brain::MissionCMD::MISSION_CANCEL)
+        {
+            missionCMD = iv::brain::MissionCMD::MISSION_RESERVED;
+            ui->missionResButton->setChecked(true);
+        }
+        if(workCMD == iv::brain::WorkCMD::WORK_START)
+        {
+            workCMD = iv::brain::WorkCMD::WORK_RESERVED;
+            ui->workResButton->setChecked(true);
+        }
+        if(remoteCtrlCMD == iv::brain::RemoteCtrlCMD::REMOTE_CTRL_EXIT)
+        {
+            remoteCtrlCMD = iv::brain::RemoteCtrlCMD::REMOTE_CTRL_RESERVED;
+            ui->remoteResButton->setChecked(true);
+        }
+        if(waitingStationArrived == true)
+        {
+            waitingStationArrived = false;
+            ui->waitSta_checkBox->setChecked(false);
+        }
+        break;
+    case 1:
+        ui->FSMStateTextBrowser->setText("1任务中");
+        if(missionCMD == iv::brain::MissionCMD::MISSION_START)
+        {
+            missionCMD = iv::brain::MissionCMD::MISSION_RESERVED;
+            ui->missionResButton->setChecked(true);
+        }
+        if(remoteCtrlCMD == iv::brain::RemoteCtrlCMD::REMOTE_CTRL_EXIT)
+        {
+            remoteCtrlCMD = iv::brain::RemoteCtrlCMD::REMOTE_CTRL_RESERVED;
+            ui->remoteResButton->setChecked(true);
+        }
+        break;
+    case 2:
+        ui->FSMStateTextBrowser->setText("2人工接管");
+        if(remoteCtrlCMD == iv::brain::RemoteCtrlCMD::REMOTE_CTRL_ENTER)
+        {
+            remoteCtrlCMD = iv::brain::RemoteCtrlCMD::REMOTE_CTRL_RESERVED;
+            ui->remoteResButton->setChecked(true);
+        }
+        break;
+    case 3:
+        ui->FSMStateTextBrowser->setText("3停工停车");
+        if(remoteCtrlCMD == iv::brain::RemoteCtrlCMD::REMOTE_CTRL_EXIT)
+        {
+            remoteCtrlCMD = iv::brain::RemoteCtrlCMD::REMOTE_CTRL_RESERVED;
+            ui->remoteResButton->setChecked(true);
+        }
+        if(maintainStationArrived == true)
+        {
+            maintainStationArrived = false;
+            ui->maintainSta_checkBox->setChecked(false);
+        }
+        break;
+    case 4:
+        ui->FSMStateTextBrowser->setText("4返程");
+        if(remoteCtrlCMD == iv::brain::RemoteCtrlCMD::REMOTE_CTRL_EXIT)
+        {
+            remoteCtrlCMD = iv::brain::RemoteCtrlCMD::REMOTE_CTRL_RESERVED;
+            ui->remoteResButton->setChecked(true);
+        }
+        break;
+    case 5:
+        ui->FSMStateTextBrowser->setText("5返库");
+        if(workCMD == iv::brain::WorkCMD::WORK_STOP)
+        {
+            workCMD = iv::brain::WorkCMD::WORK_RESERVED;
+            ui->workResButton->setChecked(true);
+        }
+        if(remoteCtrlCMD == iv::brain::RemoteCtrlCMD::REMOTE_CTRL_EXIT)
+        {
+            remoteCtrlCMD = iv::brain::RemoteCtrlCMD::REMOTE_CTRL_RESERVED;
+            ui->remoteResButton->setChecked(true);
+        }
+        break;
+    default:
+        break;
+    }
+}

+ 73 - 0
src/tool/tool_FSM_Test/mainwindow.h

@@ -0,0 +1,73 @@
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QMainWindow>
+#include <QTimer>
+#include <QDateTime>
+
+#include "modulecomm.h"
+#include "FSMSkipCMD.pb.h"
+#include "brainstate.pb.h"
+
+QT_BEGIN_NAMESPACE
+namespace Ui { class MainWindow; }
+QT_END_NAMESPACE
+
+#ifndef IV_MSGUNIT
+#define IV_MSGUNIT
+
+namespace iv {
+struct msgunit
+{
+    char mstrmsgname[256];
+    int mnBufferSize = 10000;
+    int mnBufferCount = 1;
+    void * mpa = nullptr;
+    std::shared_ptr<char> mpstrmsgdata;
+    int mndatasize = 0;
+    bool mbRefresh = false;
+    bool mbImportant = false;
+    int mnkeeptime = 100;
+};
+}
+
+#endif
+
+class MainWindow : public QMainWindow
+{
+    Q_OBJECT
+
+public:
+    MainWindow(QWidget *parent = nullptr);
+    ~MainWindow();
+    void ListenBrainStateMsg(const char * strdata,const unsigned int nSize,const unsigned int index,const QDateTime * dt,const char * strmemname);
+
+private:
+    Ui::MainWindow *ui;
+
+    iv::msgunit shmFSMSkipCMD;
+    iv::msgunit shmBrainState;
+
+    QTimer signalSendTimer;
+    uint32_t FSMState = 0;
+    iv::brain::MissionCMD missionCMD = iv::brain::MissionCMD::MISSION_RESERVED; // 任务开始 完成 取消
+    iv::brain::WorkCMD workCMD = iv::brain::WorkCMD::WORK_RESERVED; // 开工 停工
+    iv::brain::RemoteCtrlCMD remoteCtrlCMD = iv::brain::RemoteCtrlCMD::REMOTE_CTRL_RESERVED; // 人工接管进入 退出
+    bool waitingStationArrived = false; // 到达等待站点
+    bool maintainStationArrived = false; // 到达维护站点
+
+public slots:
+    void signalSend_Timeout(void);
+private slots:
+    void on_missionStaButton_clicked(bool checked);
+    void on_missionFinButton_clicked(bool checked);
+    void on_missionCanButton_clicked(bool checked);
+    void on_workStaButton_clicked(bool checked);
+    void on_workStoButton_clicked(bool checked);
+    void on_remoteExiButton_clicked(bool checked);
+    void on_remoteEntButton_clicked(bool checked);
+    void on_waitSta_checkBox_clicked(bool checked);
+    void on_maintainSta_checkBox_clicked(bool checked);
+    void on_comboBox_activated(int index);
+};
+#endif // MAINWINDOW_H

+ 430 - 0
src/tool/tool_FSM_Test/mainwindow.ui

@@ -0,0 +1,430 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+  <property name="enabled">
+   <bool>true</bool>
+  </property>
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>549</width>
+    <height>551</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>MainWindow</string>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <widget class="QSplitter" name="splitter">
+    <property name="geometry">
+     <rect>
+      <x>21</x>
+      <y>21</y>
+      <width>211</width>
+      <height>501</height>
+     </rect>
+    </property>
+    <property name="minimumSize">
+     <size>
+      <width>201</width>
+      <height>501</height>
+     </size>
+    </property>
+    <property name="orientation">
+     <enum>Qt::Vertical</enum>
+    </property>
+    <widget class="QGroupBox" name="missionGroupBox">
+     <property name="minimumSize">
+      <size>
+       <width>161</width>
+       <height>151</height>
+      </size>
+     </property>
+     <property name="title">
+      <string>任务开始、完成、取消</string>
+     </property>
+     <widget class="QWidget" name="layoutWidget">
+      <property name="geometry">
+       <rect>
+        <x>10</x>
+        <y>30</y>
+        <width>142</width>
+        <height>112</height>
+       </rect>
+      </property>
+      <layout class="QVBoxLayout" name="verticalLayout">
+       <item>
+        <widget class="QRadioButton" name="missionResButton">
+         <property name="text">
+          <string>mission reserved</string>
+         </property>
+         <property name="checked">
+          <bool>true</bool>
+         </property>
+         <attribute name="buttonGroup">
+          <string notr="true">mission_buttonGroup</string>
+         </attribute>
+        </widget>
+       </item>
+       <item>
+        <widget class="QRadioButton" name="missionStaButton">
+         <property name="text">
+          <string>mission start</string>
+         </property>
+         <attribute name="buttonGroup">
+          <string notr="true">mission_buttonGroup</string>
+         </attribute>
+        </widget>
+       </item>
+       <item>
+        <widget class="QRadioButton" name="missionFinButton">
+         <property name="text">
+          <string>mission finished</string>
+         </property>
+         <attribute name="buttonGroup">
+          <string notr="true">mission_buttonGroup</string>
+         </attribute>
+        </widget>
+       </item>
+       <item>
+        <widget class="QRadioButton" name="missionCanButton">
+         <property name="text">
+          <string>mission cancel</string>
+         </property>
+         <property name="checked">
+          <bool>false</bool>
+         </property>
+         <attribute name="buttonGroup">
+          <string notr="true">mission_buttonGroup</string>
+         </attribute>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+    </widget>
+    <widget class="QGroupBox" name="workGroupBox">
+     <property name="minimumSize">
+      <size>
+       <width>131</width>
+       <height>121</height>
+      </size>
+     </property>
+     <property name="title">
+      <string>开工、停工</string>
+     </property>
+     <widget class="QWidget" name="layoutWidget">
+      <property name="geometry">
+       <rect>
+        <x>10</x>
+        <y>30</y>
+        <width>125</width>
+        <height>83</height>
+       </rect>
+      </property>
+      <layout class="QVBoxLayout" name="verticalLayout_2">
+       <item>
+        <widget class="QRadioButton" name="workStaButton">
+         <property name="text">
+          <string>work start</string>
+         </property>
+         <attribute name="buttonGroup">
+          <string notr="true">work_buttonGroup</string>
+         </attribute>
+        </widget>
+       </item>
+       <item>
+        <widget class="QRadioButton" name="workStoButton">
+         <property name="text">
+          <string>work stop</string>
+         </property>
+         <attribute name="buttonGroup">
+          <string notr="true">work_buttonGroup</string>
+         </attribute>
+        </widget>
+       </item>
+       <item>
+        <widget class="QRadioButton" name="workResButton">
+         <property name="text">
+          <string>work reserved</string>
+         </property>
+         <property name="checked">
+          <bool>true</bool>
+         </property>
+         <attribute name="buttonGroup">
+          <string notr="true">work_buttonGroup</string>
+         </attribute>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+    </widget>
+    <widget class="QGroupBox" name="remoteGroupBox">
+     <property name="minimumSize">
+      <size>
+       <width>151</width>
+       <height>121</height>
+      </size>
+     </property>
+     <property name="title">
+      <string>远控退出、进入</string>
+     </property>
+     <widget class="QWidget" name="layoutWidget">
+      <property name="geometry">
+       <rect>
+        <x>10</x>
+        <y>30</y>
+        <width>141</width>
+        <height>83</height>
+       </rect>
+      </property>
+      <layout class="QVBoxLayout" name="verticalLayout_3">
+       <item>
+        <widget class="QRadioButton" name="remoteExiButton">
+         <property name="text">
+          <string>remote exit</string>
+         </property>
+         <attribute name="buttonGroup">
+          <string notr="true">remote_buttonGroup</string>
+         </attribute>
+        </widget>
+       </item>
+       <item>
+        <widget class="QRadioButton" name="remoteEntButton">
+         <property name="text">
+          <string>remote enter</string>
+         </property>
+         <attribute name="buttonGroup">
+          <string notr="true">remote_buttonGroup</string>
+         </attribute>
+        </widget>
+       </item>
+       <item>
+        <widget class="QRadioButton" name="remoteResButton">
+         <property name="text">
+          <string>remote reserved</string>
+         </property>
+         <property name="checked">
+          <bool>true</bool>
+         </property>
+         <attribute name="buttonGroup">
+          <string notr="true">remote_buttonGroup</string>
+         </attribute>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+    </widget>
+    <widget class="QGroupBox" name="arrivedGroupBox">
+     <property name="minimumSize">
+      <size>
+       <width>211</width>
+       <height>91</height>
+      </size>
+     </property>
+     <property name="title">
+      <string>到达某位置</string>
+     </property>
+     <widget class="QWidget" name="layoutWidget">
+      <property name="geometry">
+       <rect>
+        <x>10</x>
+        <y>30</y>
+        <width>189</width>
+        <height>54</height>
+       </rect>
+      </property>
+      <layout class="QVBoxLayout" name="verticalLayout_4">
+       <item>
+        <widget class="QCheckBox" name="waitSta_checkBox">
+         <property name="text">
+          <string>waiting station arrived</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QCheckBox" name="maintainSta_checkBox">
+         <property name="text">
+          <string>maintain station arrived</string>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+    </widget>
+   </widget>
+   <widget class="QWidget" name="layoutWidget">
+    <property name="geometry">
+     <rect>
+      <x>260</x>
+      <y>20</y>
+      <width>262</width>
+      <height>292</height>
+     </rect>
+    </property>
+    <layout class="QVBoxLayout" name="verticalLayout_5">
+     <property name="leftMargin">
+      <number>3</number>
+     </property>
+     <property name="topMargin">
+      <number>3</number>
+     </property>
+     <property name="rightMargin">
+      <number>3</number>
+     </property>
+     <property name="bottomMargin">
+      <number>3</number>
+     </property>
+     <item>
+      <widget class="QLabel" name="label">
+       <property name="minimumSize">
+        <size>
+         <width>105</width>
+         <height>32</height>
+        </size>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>105</width>
+         <height>32</height>
+        </size>
+       </property>
+       <property name="font">
+        <font>
+         <pointsize>16</pointsize>
+        </font>
+       </property>
+       <property name="text">
+        <string>当前状态:</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QTextBrowser" name="FSMStateTextBrowser">
+       <property name="minimumSize">
+        <size>
+         <width>256</width>
+         <height>61</height>
+        </size>
+       </property>
+       <property name="font">
+        <font>
+         <pointsize>24</pointsize>
+        </font>
+       </property>
+       <property name="html">
+        <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Ubuntu'; font-size:24pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;0待命停车&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QLabel" name="label_2">
+       <property name="minimumSize">
+        <size>
+         <width>101</width>
+         <height>181</height>
+        </size>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>101</width>
+         <height>181</height>
+        </size>
+       </property>
+       <property name="font">
+        <font>
+         <pointsize>14</pointsize>
+        </font>
+       </property>
+       <property name="text">
+        <string>0:待命停车
+1:任务中
+2:人工接管
+3:停工停车
+4:返程
+5:返库</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </widget>
+   <widget class="QWidget" name="">
+    <property name="geometry">
+     <rect>
+      <x>260</x>
+      <y>400</y>
+      <width>220</width>
+      <height>27</height>
+     </rect>
+    </property>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <widget class="QLabel" name="label_3">
+       <property name="minimumSize">
+        <size>
+         <width>101</width>
+         <height>17</height>
+        </size>
+       </property>
+       <property name="text">
+        <string>设定当前状态</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QComboBox" name="comboBox">
+       <property name="minimumSize">
+        <size>
+         <width>111</width>
+         <height>25</height>
+        </size>
+       </property>
+       <item>
+        <property name="text">
+         <string>0待命停车</string>
+        </property>
+       </item>
+       <item>
+        <property name="text">
+         <string>1任务中</string>
+        </property>
+       </item>
+       <item>
+        <property name="text">
+         <string>2人工接管</string>
+        </property>
+       </item>
+       <item>
+        <property name="text">
+         <string>3停工停车</string>
+        </property>
+       </item>
+       <item>
+        <property name="text">
+         <string>4返程</string>
+        </property>
+       </item>
+       <item>
+        <property name="text">
+         <string>5返库</string>
+        </property>
+       </item>
+      </widget>
+     </item>
+    </layout>
+   </widget>
+  </widget>
+ </widget>
+ <resources/>
+ <connections/>
+ <buttongroups>
+  <buttongroup name="work_buttonGroup"/>
+  <buttongroup name="mission_buttonGroup"/>
+  <buttongroup name="remote_buttonGroup"/>
+ </buttongroups>
+</ui>

+ 55 - 0
src/tool/tool_FSM_Test/tool_FSM_Test.pro

@@ -0,0 +1,55 @@
+QT       += core gui
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+CONFIG += c++11
+
+# The following define makes your compiler emit warnings if you use
+# any Qt feature that has been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if it uses deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
+
+SOURCES += \
+    ../../include/msgtype/FSMSkipCMD.pb.cc \
+    ../../include/msgtype/brainstate.pb.cc \
+    main.cpp \
+    mainwindow.cpp
+
+HEADERS += \
+    ../../include/msgtype/FSMSkipCMD.pb.h \
+    ../../include/msgtype/brainstate.pb.h \
+    mainwindow.h
+
+FORMS += \
+    mainwindow.ui
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target
+
+!include(../../../include/common.pri ) {
+    error( "Couldn't find the common.pri file!" )
+}
+
+!include(../../../include/ivprotobuf.pri ) {
+    error( "Couldn't find the ivprotobuf.pri file!" )
+}
+
+!include(../../../include/ivboost.pri ) {
+    error( "Couldn't find the ivboost.pri file!" )
+}
+
+!include(../../../include/ivgrpc.pri ) {
+    error( "Couldn't find the ivgrpc.pri file!" )
+}
+
+!include(../../../include/ivyaml-cpp.pri ) {
+    error( "Couldn't find the ivyaml-cpp.pri file!" )
+}