999精品在线视频,手机成人午夜在线视频,久久不卡国产精品无码,中日无码在线观看,成人av手机在线观看,日韩精品亚洲一区中文字幕,亚洲av无码人妻,四虎国产在线观看 ?

一種新型輕型機械臂示教軟件架構設計

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

王祺+王堃+張璇琛

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

關鍵詞:TCP/IP通訊;圖形界面卡死;QTcpSocket

DOIDOI:10.11907/rjdk.172360

中圖分類號:TP319

文獻標識碼:A 文章編號:1672-7800(2018)002-0124-04

0 引言

圖1是六軸輕型機械臂控制系統。控制軟件安裝在控制器里,示教器是控制器外的觸屏。控制器和示教器連在一起是低配的平板電腦,運算和儲存要求不高。PCAN又叫做PCAN-USB,是一個CAN轉USB接口,通過它可以將CAN網絡上的報文通過USB接口傳輸到PC上,通過相關軟件查看CAN報文。PCAN的另一端連接控制器CAN卡,CAN卡與六軸機械臂相連。使用Qt編寫程序,語言為C++。

1 界面卡死原因

“界面卡死”是計算機系統由于過量的進程資源消耗,使圖形界面進程受到影響的現象。控制程序較為復雜的指令有發送和接收報文、進行運動軌跡規劃等。用戶通過示教器的圖形界面發出指令,在進行稍微復雜的處理時就會有延遲,使得界面(GUI)卡死。對此進行改進,將控制器的程序拆分為兩個,如圖2所示。一個程序是用戶界面程序(GUI),稱為RH-LBR,負責收集用戶指令,另一個程序Communication_APP專門負責收集下位機發來的報文,以及通過GUI指令向下位機發送指令。這樣耗時的處理都由Communication_APP來處理,用戶交互界面RH-LBR不會被卡死。兩個程序之間的通訊模式為TCP/IP。

2 建立TCP通訊

下面分別介紹RH_LBR和Communication_APP這兩個程序里負責通訊的類。CIRT_LBR_GUI類定義RH_LBR程序的GUI,有信號與槽函數和ControllerSocket類互通消息。ControllerSocket類定義TCP里的用戶端類。Communication_APP程序里有TcpTransaction類,主要定義TCP里的服務器端,見圖3。

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

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

2.1 RH_LBR用戶界面程序兩個主要類

RH_LBR程序里有兩個主要類:CIRT_LBR_GUI和ControllerSocket類。

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

void CIRT_LBR_GUI::initTCPConnection()

{

開始新建socket的線程和socket的對象

TCPConnectionThread=new QThread;

controllerSocket=new ControllerSocket;

controllerSocket->moveToThread(TCPConnectionThread);

下一行代碼表示用GUI界面的信號函數觸發ControllerSocket類的TCP連接函數:

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

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

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

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

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

QString ControllerSocket::hostName="127.0.0.1";TCP主機名,不是實際的,可自行設定

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發來的信息

}

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()函數表示接收Communication_APP這個程序發來的信息,會有對應的sendMessage函數在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);這個函數表示消息格式識別,具體代碼省略,這個函數會發送Q_EMIT信號函數給CIRT_LBR_GUI類}}}

void ControllerSocket::writeBytes(const QString & Message)

這個writeBytes函數傳輸信息,使得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通訊服務器端程序

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

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

QDataStream in;用于和驅動器通信的子線程;

HardSoft_Interface*HS_Interface;這是和硬件連接的類,負責向下位機發送報文,不詳細介紹。

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通信的網絡配置槽函數,具體代碼如下:

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

將信號與槽進行連接

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

quitButton->setAutoDefault(false);

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

注意Initial函數表示每當一個新的客戶端連接上服務器后,不管前面的客戶端是否退出,應該delete之前的tcpsocket,而不只是修改服務器的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一旦退出,服務器也必須退出,頁面布局代碼忽略}

void TcpTransaction::sessionOpened()

{tcpsocket=Q_NULLPTR;

tcpServer=new QTcpServer(this);

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

int port=30001;

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

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

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

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

close();

return;}}

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

void TcpTransaction::Initial()

{如果客戶端退出,新客戶端連接到服務器,若原來的tcpsocket不被銷毀,可能會導致內存泄漏,所以刪除之前的tcpsocket

if(tcpsocket)

delete tcpsocket;

tcpsocket=tcpServer->nextPendingConnection();

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

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

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

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

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

將所有用戶發來的指令解析后發送給子線程:HS_Interface,由HS_Interface經過Pcan發送給can總線,從而和驅動器通信。

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

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

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

下面的readMessage函數獲取用戶程序發送的全部報文,解析后通過信號發送給子線程: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函數將需要發送的信息發送出去:

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 軟件架構改進

通過以上步驟,將耗時的程序以及與下位機通訊的程序都轉移為GUI界面卡死問題。pcan與can卡之間通訊不穩定,有很多超時現象,軟件架構改進方向是:控制器和can卡采用TCP直接通訊,不再借用pcan轉換,使控制系統更加穩定,見圖4。通過控制輕型六軸機械臂運動,證明此軟件有效,解決了界面卡死問題。

參考文獻:

[1] 謝希仁.計算機網絡教程[M].北京:人民郵電出版社,2002.

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

[3] 凌俊峰.TCP/IP協議淺釋[J].韶關學院學報,2001(9):138-142.

[4] 張延雙,張建標,王全民.TCP/IP協議分析及應用[M].北京:機械工業出版社,2007.

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

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

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

[8] 黃維通.面向對象程序設計與QT程序設計入門[M].北京:北京航空航天大學出版社,2010.

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

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

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

[12] 李宋琛.Linux面向對象窗口高級編程[M].北京:科學出版社,2001.

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

主站蜘蛛池模板: 久久特级毛片| 亚洲欧美一区在线| 免费国产黄线在线观看| 亚洲日韩高清在线亚洲专区| 青青久久91| 亚洲三级视频在线观看| 波多野结衣一二三| 国产精品护士| www.日韩三级| 欧美午夜在线观看| 欧美国产另类| 日韩av无码DVD| 亚洲成人黄色网址| 91www在线观看| 欧美在线一级片| 91po国产在线精品免费观看| 午夜天堂视频| 国产在线观看人成激情视频| 中文国产成人精品久久| 国产激情无码一区二区免费| 无码精油按摩潮喷在线播放| 播五月综合| 亚洲AV无码久久精品色欲| 色噜噜综合网| 国产69囗曝护士吞精在线视频| 无码人中文字幕| 毛片一级在线| 第一区免费在线观看| 亚洲中文字幕在线精品一区| 首页亚洲国产丝袜长腿综合| 美女被操91视频| 国产黑人在线| 成人综合久久综合| 亚洲无码37.| 99久久精品久久久久久婷婷| 亚洲中文精品人人永久免费| 日本免费新一区视频| 久久熟女AV| 欧美亚洲网| 尤物特级无码毛片免费| 日韩 欧美 国产 精品 综合| 国产午夜精品鲁丝片| 国产成人8x视频一区二区| 四虎永久免费地址| 在线国产91| 中文字幕亚洲乱码熟女1区2区| 国产91av在线| 免费欧美一级| 最新国产在线| 日韩高清中文字幕| 日韩 欧美 小说 综合网 另类| 欧美日韩成人在线观看| 精品国产99久久| 亚洲swag精品自拍一区| 日韩午夜伦| 日本一区高清| 欧美精品一区二区三区中文字幕| 精品无码一区二区三区在线视频| 亚洲免费人成影院| 亚洲欧美成人影院| 夜夜高潮夜夜爽国产伦精品| 热伊人99re久久精品最新地| 免费无遮挡AV| 狠狠亚洲婷婷综合色香| 伊人无码视屏| 亚洲精品大秀视频| 99视频在线免费看| 欧美亚洲第一页| 99久久精品视香蕉蕉| 在线永久免费观看的毛片| 久久男人视频| 中文字幕欧美日韩| 国产资源免费观看| 亚洲日韩精品伊甸| 国产精品福利导航| 成人福利在线视频免费观看| 91黄色在线观看| 在线亚洲小视频| 亚洲欧美激情另类| 四虎永久在线| 九九久久99精品| 日韩专区第一页|