因爲ros的action和service都是單獨運行在線程裏,所以想在action中調用qt的tcp不是發不出去數據就是接收不到數據。這裏經過測試,發現可以如下修改使用,不過不建議這樣用,是因爲軟件架構沒有設計好纔出此下策。
如下
Q_EMIT tcpSendMsg();
tcpClient_->waitForReadyRead(5);
while(i--)
{
msDelay(10);
while(tcpClient_->bytesAvailable()>0)
{
QByteArray datagram;
datagram.resize(tcpClient_->bytesAvailable());
tcpClient_->read(datagram.data(),datagram.size());
QString rcvMsg = QString::fromUtf8(datagram,datagram.size());
//if(datagram.at(0) == 'O')
//{
std::string x_value,y_value,angle;
x_value = get_du_string(datagram,0);
y_value = get_du_string(datagram,13);
angle = get_du_string(datagram,26);
std::string final_data;
final_data = x_value + "," + y_value + "," + angle;
recv_data = QString(final_data.c_str());
return true;
}
}
在線程和主線程通過信號槽機制,讓主線程發送數據,當然tcpsocket對象是在主線程實例化的,然後通過指針傳遞給工作線程(即ros的線程), tcpClient_->waitForReadyRead(5);這一句非常關鍵,還有參數5一定要寫,5代表5秒後函數返回,不然函數會阻塞在這裏,導致數據接收錯亂。
好了,把其他代碼也放在這裏
QObject::connect(&qnode, SIGNAL(tcpSendMsg()), this, SLOT(ui_tcpSendMsg()));
void MainWindow::ui_tcpSendMsg()
{
//send data to vision server
QByteArray datagram;
//datagram = send_data.toUtf8();
QString order = "54 31 0d 0a";
//change to hex str;
QStringList hexStr = order.split(" ",QString::SkipEmptyParts);
int hexSize = hexStr.size();
for(int i=0;i<hexSize;i++){
QString hexSubStr = hexStr.at(i);
datagram.append(ConvertHexStr(hexSubStr));
}
datagram.resize(hexSize);
if(datagram.size()==0) return;
tcpClientSocket->write(datagram.data(), datagram.size());
}
難道要這麼痛苦的用以上這種方式嗎?當然不是,發現一個開源的夾爪包,自己用系統的socket進行通訊,是完全沒有像qt這樣的問題,而且他有串口和網絡通訊2種方式,對於像我這樣的小白再好不過的學習教程。另他還有端口綁定腳本,真是不錯
分享如下:
https://github.com/MRwangmaomao/dh_hand_driver