因为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