亚洲免费av电影一区二区三区,日韩爱爱视频,51精品视频一区二区三区,91视频爱爱,日韩欧美在线播放视频,中文字幕少妇AV,亚洲电影中文字幕,久久久久亚洲av成人网址,久久综合视频网站,国产在线不卡免费播放

        ?

        一種新型輕型機(jī)械臂示教軟件架構(gòu)設(shè)計(jì)

        2018-03-10 00:48:22王祺王堃張璇琛
        軟件導(dǎo)刊 2018年2期

        王祺+王堃+張璇琛

        摘 要:傳統(tǒng)輕型六軸機(jī)械臂控制軟件構(gòu)架一般包括控制器、示教器、canopen通訊等部分。傳統(tǒng)控制器是一個(gè)程序,機(jī)械臂動(dòng)作參數(shù)設(shè)定時(shí),一個(gè)動(dòng)作信號(hào)需要一組控制器參數(shù),大量的數(shù)據(jù)收發(fā)常常引發(fā)主線程與其它線程爭奪資源而出現(xiàn)死鎖,導(dǎo)致主線程不能繼續(xù)往下執(zhí)行,出現(xiàn)卡死。對(duì)此,使用Qt軟件及C++語言,開發(fā)了一款新型六軸機(jī)械臂控制軟件。采用TCP/IP通訊實(shí)現(xiàn)程序間通訊,多線程提高單個(gè)程序效率,以QTcpSocket類進(jìn)行網(wǎng)絡(luò)編程。通過控制輕型六軸機(jī)械臂運(yùn)動(dòng)實(shí)驗(yàn),證明此控制軟件有效、穩(wěn)定,能解決界面卡死問題,具有良好的可擴(kuò)展性與可移植性,界面友好,運(yùn)行流暢。

        關(guān)鍵詞:TCP/IP通訊;圖形界面卡死;QTcpSocket

        DOIDOI:10.11907/rjdk.172360

        中圖分類號(hào):TP319

        文獻(xiàn)標(biāo)識(shí)碼:A 文章編號(hào):1672-7800(2018)002-0124-04

        0 引言

        圖1是六軸輕型機(jī)械臂控制系統(tǒng)??刂栖浖惭b在控制器里,示教器是控制器外的觸屏??刂破骱褪窘唐鬟B在一起是低配的平板電腦,運(yùn)算和儲(chǔ)存要求不高。PCAN又叫做PCAN-USB,是一個(gè)CAN轉(zhuǎn)USB接口,通過它可以將CAN網(wǎng)絡(luò)上的報(bào)文通過USB接口傳輸?shù)絇C上,通過相關(guān)軟件查看CAN報(bào)文。PCAN的另一端連接控制器CAN卡,CAN卡與六軸機(jī)械臂相連。使用Qt編寫程序,語言為C++。

        1 界面卡死原因

        “界面卡死”是計(jì)算機(jī)系統(tǒng)由于過量的進(jìn)程資源消耗,使圖形界面進(jìn)程受到影響的現(xiàn)象??刂瞥绦蜉^為復(fù)雜的指令有發(fā)送和接收?qǐng)?bào)文、進(jìn)行運(yùn)動(dòng)軌跡規(guī)劃等。用戶通過示教器的圖形界面發(fā)出指令,在進(jìn)行稍微復(fù)雜的處理時(shí)就會(huì)有延遲,使得界面(GUI)卡死。對(duì)此進(jìn)行改進(jìn),將控制器的程序拆分為兩個(gè),如圖2所示。一個(gè)程序是用戶界面程序(GUI),稱為RH-LBR,負(fù)責(zé)收集用戶指令,另一個(gè)程序Communication_APP專門負(fù)責(zé)收集下位機(jī)發(fā)來的報(bào)文,以及通過GUI指令向下位機(jī)發(fā)送指令。這樣耗時(shí)的處理都由Communication_APP來處理,用戶交互界面RH-LBR不會(huì)被卡死。兩個(gè)程序之間的通訊模式為TCP/IP。

        2 建立TCP通訊

        下面分別介紹RH_LBR和Communication_APP這兩個(gè)程序里負(fù)責(zé)通訊的類。CIRT_LBR_GUI類定義RH_LBR程序的GUI,有信號(hào)與槽函數(shù)和ControllerSocket類互通消息。ControllerSocket類定義TCP里的用戶端類。Communication_APP程序里有TcpTransaction類,主要定義TCP里的服務(wù)器端,見圖3。

        在RH_LBR程序的ControllerSocket類中,重要函數(shù)如下:①void ControllerSocket::connectToController()建立TCP連接;②void ControllerSocket::readMessage()接收Communication_APP這個(gè)程序發(fā)來的信息,會(huì)有對(duì)應(yīng)的sendMessage函數(shù)在Communication_APP程序里;③void ControllerSocket::writeBytes(const QString & Message)傳輸信息,使Communication_APP可以接收到信息。

        在Communication_APP程序的TcpTransaction類中,重要函數(shù)有:①void TcpTransaction::sessionOpened()。TCP通信的網(wǎng)絡(luò)配置槽函數(shù);②void TcpTransaction::readMessage()。獲取用戶程序發(fā)送的全部報(bào)文,并解析后通過信號(hào)發(fā)送給子線程:HS_Interface;③void TcpTransaction::sendMessage(const QString & Message)。通過本函數(shù)將需要發(fā)送ControllerSocket類的信息發(fā)送出去。

        2.1 RH_LBR用戶界面程序兩個(gè)主要類

        RH_LBR程序里有兩個(gè)主要類:CIRT_LBR_GUI和ControllerSocket類。

        在CIRT_LBR_GUI類中用信號(hào)與槽函數(shù)調(diào)用ControllerSocket類中的startTCPConnection()函數(shù),建立TCP連接。

        void CIRT_LBR_GUI::initTCPConnection()

        {

        開始新建socket的線程和socket的對(duì)象

        TCPConnectionThread=new QThread;

        controllerSocket=new ControllerSocket;

        controllerSocket->moveToThread(TCPConnectionThread);

        下一行代碼表示用GUI界面的信號(hào)函數(shù)觸發(fā)ControllerSocket類的TCP連接函數(shù):

        connect(this,SIGNAL(startTCPConnection()),controllerSocket,SLOT(startTCPConnection()));

        下一行代碼表示ControllerSocket類的TCP連接結(jié)果反饋給GUI界面:

        connect(controllerSocket,SIGNAL(socketConnectionResult(bool)),this,SLOT(getSocketConnectionResult(bool)));

        TCPConnectionThread->start();開始事件循環(huán)}endprint

        下面是ControllerSocket類中定義的一些參數(shù)和槽函數(shù)。

        QString ControllerSocket::hostName="127.0.0.1";TCP主機(jī)名,不是實(shí)際的,可自行設(shè)定

        int ControllerSocket::portNo=30001;TCP端口名

        QTcpSocket*socket;

        QDataStream dataInputStream;

        ControllerSocket::ControllerSocket(QObject*parent):QObject(parent)

        {socket=new QTcpSocket(this);新建socket

        connect(socket,SIGNAL(connected()),this,SLOT(onConnected()));

        connect(socket,SIGNAL(disconnected()),this,SLOT(onDisconnected()));

        connect(socket,SIGNAL(readyRead()),this,SLOT(readMessage()));讀取socket發(fā)來的信息

        }

        void ControllerSocket::startTCPConnection()

        {connectToController();}

        void ControllerSocket::connectToController()

        {socket->connectToHost(hostName,portNo);

        if(!socket->waitForConnected())

        {qDebug()<<"can not connect to controller"; return;}

        dataInputStream.setDevice(socket);

        dataInputStream.setVersion(QDataStream::Qt_4_0);}

        下面的readMessage()函數(shù)表示接收Communication_APP這個(gè)程序發(fā)來的信息,會(huì)有對(duì)應(yīng)的sendMessage函數(shù)在Communication_APP程序里。

        void ControllerSocket::readMessage()

        {std::vectormessages;

        bool committransaction=true;

        while (committransaction && socket->bytesAvailable()>0){

        dataInputStream.startTransaction();

        QString message;

        dataInputStream>>message;

        committransaction=dataInputStream.commitTransaction();

        if(committransaction)

        {messages.push_back(message);

        parseMessage(message);這個(gè)函數(shù)表示消息格式識(shí)別,具體代碼省略,這個(gè)函數(shù)會(huì)發(fā)送Q_EMIT信號(hào)函數(shù)給CIRT_LBR_GUI類}}}

        void ControllerSocket::writeBytes(const QString & Message)

        這個(gè)writeBytes函數(shù)傳輸信息,使得Communication_APP程序可以接收到信息:

        {QByteArray block;

        QDataStream out(&block, QIODevice::WriteOnly);

        out.setVersion(QDataStream::Qt_4_0);

        out<

        qDebug()<<"to server:"<

        if(socket->state()==QAbstractSocket::ConnectedState)

        {socket->write(block);

        socket->flush();}}

        2.2 Communication_APP TCP通訊服務(wù)器端程序

        Communication_APP程序最重要是TcpTransaction類,下面介紹如何建立TCP通訊和信息傳遞。

        QTcpServer*tcpServer(tcp通信的服務(wù)器);QTcpSocket*tcpsocket(tcp通信的socket);

        QDataStream in;用于和驅(qū)動(dòng)器通信的子線程;

        HardSoft_Interface*HS_Interface;這是和硬件連接的類,負(fù)責(zé)向下位機(jī)發(fā)送報(bào)文,不詳細(xì)介紹。

        QThread HS_Thread;管理HS_interface qthread類

        TcpTransaction::TcpTransaction(QWidget*parent):QDialog(parent),statusLabel(new QLabel),tcpServer(Q_NULLPTR),HS_Interface(new HardSoft_Interface()),HS_Thread(this)

        {sessionOpened();TCP通信的網(wǎng)絡(luò)配置槽函數(shù),具體代碼如下:

        HS_Interface->moveToThread(&HS_Thread);將HS_Interface移動(dòng)到子線程

        將信號(hào)與槽進(jìn)行連接

        QPushButton*quitButton=new QPushButton(tr("Quit"));

        quitButton->setAutoDefault(false);

        connect(quitButton,&QAbstractButton::clicked,this,&QWidget::close);

        注意Initial函數(shù)表示每當(dāng)一個(gè)新的客戶端連接上服務(wù)器后,不管前面的客戶端是否退出,應(yīng)該delete之前的tcpsocket,而不只是修改服務(wù)器的tcpsocket指針指向:

        connect(tcpServer,&QTcpServer::newConnection,this,&TcpTransaction::Initial);

        connect(quitButton,&QAbstractButton::clicked,HS_Interface,&HardSoft_Interface::Quit);

        onnect(HS_Interface,&HardSoft_Interface::Exit,this,&TcpTransaction::ExitHsInterface);

        connect(&HS_Thread,&QThread::finished,this,&QWidget::close);HS_interface一旦退出,服務(wù)器也必須退出,頁面布局代碼忽略}

        void TcpTransaction::sessionOpened()

        {tcpsocket=Q_NULLPTR;

        tcpServer=new QTcpServer(this);

        QString testipaddress("127.0.0.1");非實(shí)際值,只是示例

        int port=30001;

        if(!tcpServer->listen(QHostAddress(testipaddress),port)){listen函數(shù)

        QMessageBox::critical(this,tr("Communication Server"),

        tr("Unable to start the server:%1.")

        .arg(tcpServer->errorString()));

        close();

        return;}}

        Initial函數(shù)步驟:①如果有客戶連接到服務(wù)器,則delete以前的服務(wù)器tcpsocket,然后獲取新的客戶tcp指針;②連接上客戶端后,將readyread信號(hào)和readmessage槽函數(shù)進(jìn)行連接(見下面部分代碼);③將用戶指令通過信號(hào)與槽和HS_interface進(jìn)行連接;④開啟HS_INTERFACE線程。

        void TcpTransaction::Initial()

        {如果客戶端退出,新客戶端連接到服務(wù)器,若原來的tcpsocket不被銷毀,可能會(huì)導(dǎo)致內(nèi)存泄漏,所以刪除之前的tcpsocket

        if(tcpsocket)

        delete tcpsocket;

        tcpsocket=tcpServer->nextPendingConnection();

        connect(tcpsocket,&QIODevice::readyRead,this,&TcpTransaction::readMessage);

        in.setDevice(tcpsocket);將DataStream和當(dāng)前的tcpsocket綁定

        in.setVersion(QDataStream::Qt_4_0);設(shè)置DataStream的版本

        將HS_interface發(fā)來的消息通過本線程發(fā)送給用戶APP,sendMessage詳細(xì)代碼:

        connect(HS_Interface,SIGNAL(SendMessage(QString)),this,SLOT(sendMessage(QString)));

        將所有用戶發(fā)來的指令解析后發(fā)送給子線程:HS_Interface,由HS_Interface經(jīng)過Pcan發(fā)送給can總線,從而和驅(qū)動(dòng)器通信。

        connect(this,SIGNAL(InitRobot()),HS_Interface,SLOT(start()));初始化機(jī)器人

        connect(this,SIGNAL(SetJointVel(const int&,const double&)),HS_Interface,SLOT(SetJointVel(const int&,const double&)));等等,不一一列舉。

        HS_Thread.start();}開啟子線程

        下面的readMessage函數(shù)獲取用戶程序發(fā)送的全部報(bào)文,解析后通過信號(hào)發(fā)送給子線程:HS_Interface

        void TcpTransaction::readMessage()

        {

        std::vectormessages;

        bool committransaction=true;

        while(committransaction &&

        tcpsocket->bytesAvailable()>0){

        in.startTransaction();

        QString message;

        in>>message;

        committransaction=in.commitTransaction();

        if(committransaction){

        messages.push_back(message);

        int TcpExceptionCode;

        MsgData messageData=parseMessage(message,TcpExceptionCode);

        檢查TCP通信獲得的字符串是否存在異常:

        switch(TcpExceptionCode){……

        switch(messageData.type){……

        }}}}

        通過sendMessage函數(shù)將需要發(fā)送的信息發(fā)送出去:

        void TcpTransaction::sendMessage(const QString&Message)

        {

        QByteArray block;

        QDataStream out(&block,QIODevice::WriteOnly);

        out.setVersion(QDataStream::Qt_4_0);

        out<

        if(tcpsocket->state()==QAbstractSocket::ConnectedState)

        {tcpsocket->write(block);

        tcpsocket->flush();}}

        3 軟件架構(gòu)改進(jìn)

        通過以上步驟,將耗時(shí)的程序以及與下位機(jī)通訊的程序都轉(zhuǎn)移為GUI界面卡死問題。pcan與can卡之間通訊不穩(wěn)定,有很多超時(shí)現(xiàn)象,軟件架構(gòu)改進(jìn)方向是:控制器和can卡采用TCP直接通訊,不再借用pcan轉(zhuǎn)換,使控制系統(tǒng)更加穩(wěn)定,見圖4。通過控制輕型六軸機(jī)械臂運(yùn)動(dòng),證明此軟件有效,解決了界面卡死問題。

        參考文獻(xiàn):

        [1] 謝希仁.計(jì)算機(jī)網(wǎng)絡(luò)教程[M].北京:人民郵電出版社,2002.

        [2] DOUGLAS E, COMER.Internetworking With TCP/IP[Z].2001.

        [3] 凌俊峰.TCP/IP協(xié)議淺釋[J].韶關(guān)學(xué)院學(xué)報(bào),2001(9):138-142.

        [4] 張延雙,張建標(biāo),王全民.TCP/IP協(xié)議分析及應(yīng)用[M].北京:機(jī)械工業(yè)出版社,2007.

        [5] BRUCE ECKEL.Think in C++[M].劉宗田,譯.北京:機(jī)械工業(yè)出版社,2000.

        [6] JASMINBLANCHETTE, MARKSUMMERFIELD. C++GUIQt4編程[M].第2版.閆鋒欣,譯.北京:電子工業(yè)出版社,2008.

        [7] 霍亞飛.QT Creator快速入門[M].北京:北京航空航天大學(xué)出版社,2012.

        [8] 黃維通.面向?qū)ο蟪绦蛟O(shè)計(jì)與QT程序設(shè)計(jì)入門[M].北京:北京航空航天大學(xué)出版社,2010.

        [9] JIM BEVERIDGE, ROBERT WIENER,侯捷.Win32多線程序設(shè)計(jì)[M].武漢:華中科技大學(xué)出版社,2002.

        [10] 清山博客.使用SOCKET實(shí)現(xiàn)TCP/IP協(xié)議的通訊[EB/OL].http://blog.csdn.net/a497785609/article/details/12871301.

        [11] STANLEY B. LIPPMAN. C++Primer[M].北京:人民郵電出版社,2006.

        [12] 李宋琛.Linux面向?qū)ο蟠翱诟呒?jí)編程[M].北京:科學(xué)出版社,2001.

        [13] 羅亞非.基于TCP的Socket多線程通信[J].電腦知識(shí)與技術(shù),2009(2):36-39.

        丝袜美腿爆炒国产在线观看| 成人乱码一区二区三区av| 精品少妇无码av无码专区| 欧美老熟妇欲乱高清视频 | 内射人妻少妇无码一本一道| 香蕉视频在线精品视频| 欧美丰满熟妇性xxxx| 欧美猛男军警gay自慰| 国产系列丝袜熟女精品视频| 久草国产手机视频在线观看| 一级一片内射视频网址| 婷婷色综合视频在线观看| 麻豆成人精品国产免费| 亚洲国产成人手机在线观看| 天堂视频一区二区免费在线观看| 一区视频免费观看播放| 少妇夜夜春夜夜爽试看视频 | 北条麻妃国产九九九精品视频| 国产精品成人一区二区三区 | 国产丝袜高跟美腿一区在线| 干出白浆视频在线观看| 后入内射国产一区二区| 国产真实老熟女无套内射| 久久久久亚洲AV成人网毛片| 国产蜜臀精品一区二区三区| 伊人加勒比在线观看视频| 亚洲av无码国产精品草莓在线| 国产69精品久久久久9999| 无码 免费 国产在线观看91| 日韩av在线手机免费观看| 日韩国产人妻一区二区三区| 波多野结衣av手机在线观看| 成人无码网www在线观看| 高潮av一区二区三区| 国产精品婷婷久久爽一下| 边做边流奶水的人妻| 日韩精品永久免费播放平台| 国产伦奸在线播放免费| 少妇真实被内射视频三四区| 中文亚洲成a人片在线观看| 少妇熟女淫荡丰满|