定時發送力傳感器數據至機器人

每次完成一個demo都需要記下小筆記,防止忘記,實驗如圖:
在這裏插入圖片描述
在這裏插入圖片描述
第一張圖中是紅綠相接的部分是通訊結果,$表示接受完整,這裏力傳感器的頻率爲100hz,通過定時器每10ms向socket發送數據(只能有一個定時器運行!!不然發送時間不準,有滯後),機器人的同步運行週期設爲了0.008s,最小控制週期是4ms,同步運行週期必須是其整數倍。
在這裏插入圖片描述
在這裏插入圖片描述
在下位機的start()函數裏創建兩個同步任務,一個用來讀取socket,一個用來更新機器人示教器上的UI界面
本次實驗以機器人爲客戶端,地址如圖,電腦爲服務端,監聽端口號1000
在這裏插入圖片描述
下位機代碼如下
從start()開始,(同步運行任務好像有行數限制,所以儘量多用子函數,否則會報錯!!)

begin
  userPage()
  cls()
  gotoxy(0,0)
  put("Socket sensorRead測試程序:")
  taskCreateSync "readSocket",0.008,bSupervisor,readSocket(nError,nNum_FX,nNum_FY,nNum_FZ,nNum_TX,nNum_TY,nNum_TZ)
  taskCreateSync "UI",0.008,bSupervisor,UI(nNum_FX,nNum_FY,nNum_FZ,nNum_TX,nNum_TY,nNum_TZ)
  
end

readsocket()


begin
  // This program gets the parts sent by the other robot. 
  //  The parts arrive via a socket on a telegram with the format
  //  {ID=i,X=x.xxx,Y=y.yyy,RZ=r.rrr,L=l.llllll},
  //  where "{" is the initial character, "i" is the ID of the
  //  detected object, "x.xxx" is the value on X, "y.yyy" is the
  //  value on Y, "r.rrr" is the value on RZ, "l.llllll" is the
  //  latched encoder value, "," is the separator character and "}"
  //  is the end character. At the end, it sends the character "$" 
  //  as confirmation of good reception.
  // The format of the telegram is defined at the program 
  //  sendToNextRobot at the Motion library.
  //
  // Input Param
  //  none       : 
  //
  // Output Param
  //  x_nID         : ID of the detected object
  //  x_trObjectPos : Transformation of the detected object
  //  x_nEncLatchVal: Encoder latched value of the detected object
  //  x_nError      :
  //              0 = no error, one part detected.
  //             >1 = Number of parameters in error with in the
  //                   telegram read. It wasn't possible to fully
  //                   convert into a numerical value one of the
  //                   parameter within the telegram.
  //
  //{X=x.xxx,Y=y.yyy,Z=z.zzz,Rx=rx.xxx,Ry=ry.yyy,RZ=rz.zzz}
  //
  //----------------------------------------------------------------
  //
  //Init Variables
 x_nNum_FX = 0
 x_nNum_FY = 0
 x_nNum_FZ = 0
 x_nNum_TX = 0
  x_nNum_TY = 0
   x_nNum_TZ = 0
   
 
  x_nError=0
  //
  
  
  while true
     // Looks for int Character
  call waitCharOnSk("{")
  //
  // Looks for beginig of first value
  call waitCharOnSk("=")
  //
  // Recover X value
  call readValFromSk(",",x_nNum_FX,x_nError)
  if x_nError>0
    logMsg("(readSocket)>>"+sErrorCode[0])
  endIf
  //
  // Looks for beginig of next value
  call waitCharOnSk("=")
  //
  // Recover Y value
  call readValFromSk(",",x_nNum_FY,x_nError)
  if x_nError>0
    logMsg("(readSocket)>>"+sErrorCode[1])
  endIf
  //
  // Looks for beginig of next value
  call waitCharOnSk("=")
  //
  // Recover Z value
  call readValFromSk(",",x_nNum_FZ,x_nError)
  if x_nError>0
    logMsg("(readSocket)>>"+sErrorCode[2])
  endIf
  //
  // Looks for beginig of next value
  call waitCharOnSk("=")
  //
  //Recover Z value
  call readValFromSk(",",x_nNum_TX,x_nError)
  if x_nError>0
    logMsg("(readSocket)>>"+sErrorCode[3])
  endIf
  //
  // Looks for beginig of next value
  call waitCharOnSk("=")
  //
  //Recover Z value
  call readValFromSk(",",x_nNum_TY,x_nError)
  if x_nError>0
    logMsg("(readSocket)>>"+sErrorCode[4])
  endIf
  // 
  // Looks for beginig of next value
  call waitCharOnSk("=")
  //
  //Recover Z value
  call readValFromSk("}",x_nNum_TZ,x_nError)
  if x_nError>0
    logMsg("(readSocket)>>"+sErrorCode[5])
  endIf
  //
  //
  // Sends the character "$" as confirmation of good reception.
  sioSet(skFromPc,asc("$",0))
  
  delay(0)
  endWhile
 
  //
end

readvalFromSk()

begin
  // This program reads character by character on the socket until
  //  it finds a separator character. All the characters founded before
  //  this separator character are transformed on an integer value.
  //  The socket must be a socket server with timeout=0
  //
  // Input Param
  //  x_sCharacter : Character to find
  //
  // Output Param
  //  x_nValue     : Integer value read from the socket
  //  x_nError     :
  //             0 = No error
  //            +1 = Not possible to convert the string read into
  //                  a numerical value, or the string doesn't have
  //                  the right format.
  //
  //----------------------------------------------------------------
  //
  l_sStringRead=""
  l_sCharRead=""
  //
  // Read character by character until finds specific character.
  while l_sCharRead!=x_sCharacter
    // Reads one character from socket
    sioGet(skFromPc,l_nAsciiCode)
    l_sCharRead=chr(l_nAsciiCode)
    // If the character read is not the separator character, the 
    //  character read will be added to the previous characters read.
    if l_sCharRead!=x_sCharacter
      l_sStringRead=l_sStringRead+l_sCharRead
    endIf
  endWhile
  //
  // Convert string to num
  l_sStringRead=toNum(l_sStringRead,l_nValueRead,l_bResult)
  // If convertion Ok, modify parameter.
  if (l_sStringRead=="" and l_bResult==true)
    x_nValue=l_nValueRead
  else
    x_nError=x_nError+1
  endIf
  //
end

waitCharonSk()

begin
  // This program reads character by character on the socket until
  //  it finds a specific character. The socket must be a socket
  //  server with timeout=0
  //
  // Input Param
  //  x_sCharacter : Character to find
  //
  // Output Param
  //  none         : 
  //
  //----------------------------------------------------------------
  //
  l_sCharRead=""
  //
  // Read character by character until finds specific character
  while l_sCharRead!=x_sCharacter
    // Reads one character from socket
    sioGet(skFromPc,l_nAsciiCode)
    l_sCharRead=chr(l_nAsciiCode)
  endWhile
  //
end

UI()

begin
  while true
    call renew_ui(x_nNumFX,x_nNumFY,x_nNumFZ,x_nNumTX,x_nNumTY,x_nNumTZ)
    delay(0)     
  endWhile
     
end

renew_ui()

begin
  gotoxy(2,2)
      put("FX:")
      put(toString(".3",x_nNumFX))
      //
      gotoxy(2,3)
      put("FY:")
      put(toString(".3",x_nNumFY))
      //
      gotoxy(2,4)
      put("FZ:")
      put(toString(".3",x_nNumFZ))
      //
      gotoxy(2,5)
      put("TX:")
      put(toString(".3",x_nNumTX))
      //
      gotoxy(2,6)
      put("TY:")
      put(toString(".3",x_nNumTY))
      //
      gotoxy(2,7)
      put("TZ:")  
      put(toString(".3",x_nNumTZ))
end

這裏就是用子函數 call renew_ui(x_nNumFX,x_nNumFY,x_nNumFZ,x_nNumTX,x_nNumTY,x_nNumTZ),不這麼弄會報錯!!!!
stop() 裏面不用寫任何東西

begin
end

上位機是由qt+vs2010寫的 主要用到dockwidget , Coin3D ,多線程,定時器,QWT繪圖,qsocket, Optoforce API,和staublisoap
1.docketwidget框架:
主要這上面的代碼:
https://blog.csdn.net/czyt1988/article/details/51209619

去掉中間窗口的代碼, setDockNestingEnabled(true)就可以互相嵌套了

	QWidget* p = takeCentralWidget();
	if (p)
		delete p;
	//允許嵌套dock
	setDockNestingEnabled(true);
	initDocks();

ui 界面拖QDockewidget
在這裏插入圖片描述
這裏控件都是動態創建的,所以自己寫了個initDocks()函數進行初始化

public:
	//移除並隱藏所有dock
	void removeAllDock();
	//顯示dock窗口
	void showDock(const QList<int>& index = QList<int>());
	void initDocks();  //初始化界面
	void initDock_Osg();
	void initDock_Forcesensor();
	void initDock_Coin3d();
	void initDock_Output();
	void initDock_Robot_soap_socket();
	void initDock_Emulator();
	void initDock_Example();
	void initDock_sensorFXview();
	void initDock_sensorFYview();
	void initDock_sensorFZview();
	void initDock_sensorTXview();
	void initDock_sensorTYview();
	void initDock_sensorTZview();
	void initDock_Socket_sendsensordata();//socket通訊發送力信號給機器人


下次每新建一個dock都要來這初始化下

void zlc_robotplatform::initDocks()
{
	initDock_Coin3d();
	initDock_Emulator();
	initDock_Example();
	initDock_Osg();
	initDock_Output();
	initDock_Robot_soap_socket();
	initDock_Forcesensor();
	initDock_sensorFXview();
	initDock_sensorFYview();
	initDock_sensorFZview();
	initDock_sensorTXview();
	initDock_sensorTYview();
	initDock_sensorTZview();
	initDock_Socket_sendsensordata();
	

	m_docks.append(ui.dockWidget_coin3d);  //0  COIN3d視圖
	m_docks.append(ui.dockWidget_osg);     //1  osg視圖
	m_docks.append(ui.dockWidget_emulator); //2虛擬模擬器視圖
	m_docks.append(ui.dockWidget_robot_soap_socket);//3機器人通訊
	m_docks.append(ui.dockWidget_forcesensor); //4 力傳感器通訊
	m_docks.append(ui.dockWidget_output);  //5 輸出欄 
	m_docks.append(ui.dockWidget_example);  //6 示例
	m_docks.append(ui.dockWidget_sensorviewFX);  //7 sensorFX視圖
	m_docks.append(ui.dockWidget_sensorviewFY);   //8 sensorFY視圖
	m_docks.append(ui.dockWidget_sensorviewFZ);   //9 sensorFZ視圖
	m_docks.append(ui.dockWidget_sensorviewTX);   //10 sensorTX視圖
	m_docks.append(ui.dockWidget_sensorviewTY);   //11 sensorTY視圖
	m_docks.append(ui.dockWidget_sensorviewTZ);   //12 sensorTZ視圖
	m_docks.append(ui.dockWidget_socket_send_forcesensor); //13 socket send forcedata to robot
	


	removeAllDock();
	addDockWidget(Qt::LeftDockWidgetArea, ui.dockWidget_forcesensor);
	splitDockWidget(ui.dockWidget_forcesensor, ui.dockWidget_coin3d, Qt::Horizontal);
	splitDockWidget(ui.dockWidget_coin3d, ui.dockWidget_emulator, Qt::Horizontal);
	splitDockWidget(ui.dockWidget_coin3d, ui.dockWidget_output, Qt::Vertical);
	tabifyDockWidget(ui.dockWidget_forcesensor, ui.dockWidget_example);
	tabifyDockWidget(ui.dockWidget_emulator, ui.dockWidget_robot_soap_socket);
	showDock(QList<int>() << 0  << 2 << 3<< 4 << 5 << 6 );
	
}

以fx視圖爲例:
1.首先ui裏拖一個dock,改名dockWidget_sensorviewFX,在頭文件裏建個函數

public:
void initDock_sensorFXview();
void zlc_robotplatform::initDocks()
{
	initDock_sensorFXview();
	m_docks.append(ui.dockWidget_sensorviewFZ);   //9 sensorFZ視圖
}
  1. 初始化 dock 這裏可以給dock加滾輪 QScrollArea* scro_sensorFX,之前筆者想用Qcustom來繪圖的,但是發現開了4個以上界面會卡死(用的是多線程裏面emit信號,利用slot來更新ui界面,用定時器不會,但是定時器是要用在socket上,所以選擇qwt)!!!
void zlc_robotplatform::initDock_sensorFXview()
{
// 	QScrollArea* scro_sensorFX = new QScrollArea(ui.dockWidget_sensorviewFX); //這個滾動窗口在dockewidget_4上
// 	ui.dockWidget_sensorviewFX->setWidget(scro_sensorFX);
// 	sensor_custuomPlotFXview = new QCustomPlot(scro_sensorFX);
// 	scro_sensorFX->setWidget(sensor_custuomPlotFXview);
// 	sensor_custuomPlotFXview->setGeometry(0, 0, 500, 200);
// 	ui.dockWidget_sensorviewFX->setWindowTitle(tr("力傳感器FX 5s實時數據動態繪製"));
// 	sensor_GraphFX = sensor_custuomPlotFXview->addGraph();
// 	sensor_custuomPlotFXview->graph(0)->setPen(QPen(Qt::gray));
// 	sensor_custuomPlotFXview->yAxis->setLabel(tr("FX  (N)"));
// 	sensor_custuomPlotFXview->xAxis->setLabel(tr("t  (s)"));
// 	sensor_custuomPlotFXview->xAxis->setTickLabelType(QCPAxis::ltDateTime);
// 	sensor_custuomPlotFXview->xAxis->setDateTimeFormat("mm:ss");
// 	sensor_custuomPlotFXview->xAxis->setAutoTickStep(false);
// 	sensor_custuomPlotFXview->xAxis->setRange(0, 5);
// 	sensor_custuomPlotFXview->xAxis->setTickStep(1);
// 	sensor_custuomPlotFXview->replot();

	QScrollArea* scro_sensorFX = new QScrollArea(ui.dockWidget_sensorviewFX); //這個滾動窗口在dockewidget_4上
	ui.dockWidget_sensorviewFX->setWidget(scro_sensorFX);
	qwtplotFX = new QwtPlot(scro_sensorFX);
    scro_sensorFX->setWidget(qwtplotFX);
	qwtplotFX->setGeometry(0, 0, 500, 200);
	//初始化xdata,x對應長度爲5的座標,y初始全爲0
	for (int i = 0; i < 500; i++)
	{
		num_data.append(i);
		sensor_FX_data.append(0);
	}
	//qwtplotFX->setTitle("The force of X");
	qwtplotFX->setCanvasBackground(Qt::white);//背景
	qwtcurve_FX = new QwtPlotCurve();
	qwtcurve_FX->setPen(Qt::gray, 1); //曲線的顏色 寬度;
	//設置刻度
	qwtplotFX->setAxisScale(QwtPlot::yLeft, -1, 1, 1); //設置刻度範圍-2到2,間隔是1
	qwtplotFX->setAxisScale(QwtPlot::xBottom, 0, 500, 100);
	//設置網格
	QwtPlotGrid *grid = new QwtPlotGrid();
	//grid->enableX(true);//設置網格線
	grid->enableY(true);
	grid->setMajorPen(Qt::black, 0, Qt::DotLine);
	grid->attach(qwtplotFX);
	qwtcurve_FX->setSamples(num_data, sensor_FX_data);
	qwtcurve_FX->attach(qwtplotFX);
	qwtplotFX->setAxisTitle(QwtPlot::yLeft, QStringLiteral("FX  (N)"));
	//qwtplotFX->setAxisTitle(QwtPlot::xBottom, QStringLiteral("500組實時數據"));
	qwtplotFX->setTitle(tr("力傳感器FX實時數據"));
	//qwtplotFX->plotLayout();
	qwtplotFX->replot();
	

}

因爲我默認佈局窗口是這些showDock(QList() << 0 << 2 << 3<< 4 << 5 << 6 );
而 m_docks.append(ui.dockWidget_sensorviewFX); //7 sensorFX視圖,所以需要加個按鈕來顯示在這裏插入圖片描述
添加槽函數

public slots:
	void on_action_Fxviewer();

connect一下

connect(ui.action_Fxviewer,SIGNAL(triggered()),this,SLOT(on_action_Fxviewer()));

槽函數內容如下:

void zlc_robotplatform::on_action_Fxviewer()
{
	ui.dockWidget_sensorviewFX->hide();	
	ui.dockWidget_sensorviewFX->setFloating(true);
	ui.dockWidget_sensorviewFX->show();
}

如圖:帶滾輪的dock就出來了
在這裏插入圖片描述
2.多線程動態繪圖
還是以繪製Fx爲例
多線程抄誰的代碼忘記錄了。。。反正這麼寫可以安全使用該線程
signals: void myplotThread_Signal(); 是發射信號,用來更新UI

//myplotthread 
class myplotThread : public QThread
{
	Q_OBJECT

public:
	myplotThread(QObject *parent = 0);
	void run();
	void stop();
	bool m_isExist; //控制線程退出;
	QMutex m_mutex;
	
signals:
	void myplotThread_Signal();
};
//plotthread
myplotThread::myplotThread(QObject *parent)
	:QThread(parent),
	m_isExist(false)
{


}

void myplotThread::run()
{
	while (true)
	{
		m_mutex.lock();
		if (m_isExist)
			break;
		m_mutex.unlock();
		emit myplotThread_Signal();
		MySleep(10);   //這裏是我自定義的函數
	}
	m_mutex.unlock();
}
void myplotThread::stop()
{
	m_mutex.lock();
	m_isExist = true;
	m_mutex.unlock();
}


定義跟新ui的槽

public:
	myplotThread* m_plotthread;
public slots:
	void Plotthreadslot();
connect(m_plotthread, SIGNAL(myplotThread_Signal()), this, SLOT(Plotthreadslot()), Qt::QueuedConnection);

qwtplotFX->setAxisScale(QwtPlot::yLeft, minValueFX - 1, maxValueFX + 1);這裏就可以基本讓曲線在圖的中間位置而不是滿屏

void zlc_robotplatform::Plotthreadslot()
{
	sensor_FX_data.erase(sensor_FX_data.begin());
	sensor_FX_data.append(m_sensorthread->pack6D.Fx*0.1);
	qwtcurve_FX->setSamples(num_data, sensor_FX_data);
	qwtcurve_FX->attach(qwtplotFX);	
	double maxValueFX = *max_element(sensor_FX_data.begin(), sensor_FX_data.end());
	double minValueFX = *min_element(sensor_FX_data.begin(), sensor_FX_data.end());
	//qwtplotFX->setAxisAutoScale(QwtPlot::yLeft, true);
	qwtplotFX->setAxisScale(QwtPlot::yLeft, minValueFX - 1, maxValueFX + 1);
	qwtplotFX->replot();
}

3.qwt的安裝與使用
http://blog.sina.com.cn/s/blog_a6fb6cc90101gks5.html
這裏是已經編譯好的版本只需按下圖配置即可,親測可用vs2010+qt5.3.1
在這裏插入圖片描述
4.optoforce力傳感器API使用(windows32位)
下載鏈接:
反正這麼用沒問題,用以前的代碼FZ會出一個大的端口號(不知道是不是有bug)

//sensor thread
void MySleep(unsigned long p_uMillisecs)
{
	Sleep(p_uMillisecs);
}

typedef unsigned long long mytime_t;
mytime_t Now()
{
	LARGE_INTEGER frequency;
	LARGE_INTEGER timeStamp;

	QueryPerformanceFrequency(&frequency);
	QueryPerformanceCounter(&timeStamp);

	timeStamp.QuadPart *= 1000;
	timeStamp.QuadPart /= frequency.QuadPart;

	return (mytime_t)timeStamp.QuadPart;
}


mytime_t NowMicro()
{
	LARGE_INTEGER frequency;
	LARGE_INTEGER timeStamp;

	QueryPerformanceFrequency(&frequency);
	QueryPerformanceCounter(&timeStamp);

	timeStamp.QuadPart *= 1000000;
	timeStamp.QuadPart /= frequency.QuadPart;

	return (unsigned long long)timeStamp.QuadPart;
}


mytime_t ElapsedTime(mytime_t p_tTime)
{
	return Now() - p_tTime;
}


mytime_t ElapsedTimeMicro(mytime_t p_tTime)
{
	return NowMicro() - p_tTime;
}

/*
* Set the config to the DAQ
* it is a blocking function; returns true, if the sending of
* configuration is succeeded otherwise it returns false
*/
bool SetConfig(OptoDAQ & p_optoDAQ, int p_iSpeed, int p_iFilter)
{
	SensorConfig sensorConfig;
	sensorConfig.setSpeed(p_iSpeed);
	sensorConfig.setFilter(p_iFilter);
	mytime_t tNow = Now();

	bool bSuccess = false;
	do {
		bSuccess = p_optoDAQ.sendConfig(sensorConfig);
		if (bSuccess) {
			return true;
		}
		if (ElapsedTime(tNow) > 1000) {
			// 1 sec timeout
			return false;
		}
		MySleep(1);
	} while (bSuccess == false);
	return false;
}
/*
* Opens the desired port
* it returns true if port could be opened otherwise returns false
*/
bool OpenPort(OptoDAQ & p_optoDAQ, OptoPorts & p_Ports, int p_iIndex)
{
	MySleep(2500); // We wait some ms to be sure about OptoPorts enumerated PortList 
	OPort * portList = p_Ports.listPorts(true);
	int iLastSize = p_Ports.getLastSize();
	if (p_iIndex >= iLastSize) {
		// index overflow
		return false;
	}
	bool bSuccess = p_optoDAQ.open(portList[p_iIndex]);
	if (bSuccess) {
		//ShowInformation(p_optoDAQ, portList[p_iIndex]);
	}
	return bSuccess;
}


mysensorThread::mysensorThread(QObject*parent)
	:QThread(parent),
	m_isExist(false),
	writeflag(false),
	SendDataflag(false)

{


}

void mysensorThread::run()
{

	// Changeable values, feel free to play with them
	int iPortIndex = 0;  // The index of the port which will be opened
	//mytime_t tRunningTime = 600 * 1000;  // Total running time in milliseconds
	int iSpeed = 100; // Speed in Hz
	int iFilter = 15;  // Filter in Hz
	///////////////////
	if (OpenPort(optoDaq, optoPorts, iPortIndex) == false) {
		std::cout << "Could not open port" << std::endl;
		emit sensorthreadfailedSignal();
		return ;
	}
	bool bConfig = SetConfig(optoDaq, iSpeed, iFilter);
	if (bConfig == false) {
		std::cout << "Could not set config" << std::endl;
		emit sensorthreadfailedSignal();
		optoDaq.close();
		return ;
	}
	//ReadPackage6D(optoDaq,pack6D);
	int iSize = -1;
	mytime_t tNow = Now();	
	QTextStream in(&file);
	for (;;) {

		m_mutex.lock();
		if (m_isExist)
			break;
		m_mutex.unlock();
		iSize = optoDaq.read6D(pack6D, false);
		if (iSize < 0) {
			break;
		}
		if (writeflag)
		{
			GetLocalTime(&sys);
			in << sys.wHour<<":" << sys.wMinute << ":" << sys.wSecond << "." << sys.wMilliseconds << " " << pack6D.Fx*0.1 << " " << pack6D.Fy *0.1<< " " << pack6D.Fz *0.1<< " " << pack6D.Tx*0.001 << " " << pack6D.Ty*0.001 << " " << pack6D.Tz *0.001<< endl;
			
		}
 		emit sensorthreadSignal();
		emit sensor_fxviewerUpdateSignal();
		emit sensor_fyviewerUpdateSignal();
		emit sensor_fzviewerUpdateSignal();
		emit sensor_txviewerUpdateSignal();
		emit sensor_tyviewerUpdateSignal();
		emit sensor_tzviewerUpdateSignal();
		MySleep(10); //10ms
	}

	m_mutex.unlock();
	optoDaq.close();
	
	return ;


}
void mysensorThread::stop()
{
	m_mutex.lock();
	m_isExist = true;
	m_mutex.unlock();
}

5. staublisoapAPI
. 以前是使用C#動態庫,發現不是那麼好用,並且不跨平臺,目前該API暫時用於反饋機器人狀態,更多功能還在探索
6.socket通訊
qtsocket網絡通訊非常好用,github上也有很多非常好的例子,抄的關鍵代碼如下:

//socket通訊區
public:
	QTcpServer *tcpServer;//監聽套接字
	QTcpSocket *tcpSocket;//通信套接字


	//qtsocket通訊用的槽
private slots:
	void socketReadData();
	void socketDisconnected();
	void sever_new_connect();
	tcpServer = new QTcpServer;
	connect(tcpServer, &QTcpServer::newConnection, this, &zlc_robotplatform::sever_new_connect); //qt4的寫法?
zlc_robotplatform::~zlc_robotplatform()
{
	if (myviewer != NULL)
	{
		delete myviewer;
		zlc_tx90->root->unref();
	}
	tcpServer->close();
	tcpServer->deleteLater();

}
void zlc_robotplatform::socketReadData()  //讀取傳過來的數據
{
	QByteArray buffer;
	buffer = tcpSocket->readAll();

	if (!buffer.isEmpty())
	{
		QString str = tr(buffer);
	   Socket_Text_append(1, str);
	}

}
void zlc_robotplatform::sever_new_connect()
{
	tcpSocket = tcpServer->nextPendingConnection();
	QObject::connect(tcpSocket, &QTcpSocket::readyRead, this, &zlc_robotplatform::socketReadData);
	QObject::connect(tcpSocket, &QTcpSocket::disconnected, this, &zlc_robotplatform::socketDisconnected);
	Socket_Text_append(0, "server connect");
	PushButton_socket_sendforcedata->setEnabled(true);
	PushButton_socket_sendforcedata_ontime->setEnabled(true);
}
void zlc_robotplatform::socketDisconnected()
{

}
void zlc_robotplatform::on_PushButton_socket_sendforcedata_lisen_clicked()
{
	if (PushButton_socket_sendforcedata_lisen->text() == tr("監聽"))
	{
		int port = 1000;
		if (!tcpServer->listen(QHostAddress::Any, port))
		{
			
			ui.statusBar->showMessage(tr("socket連接失敗"), 1000);
			//return;
		}
		PushButton_socket_sendforcedata_lisen->setText(tr("取消監聽"));

		ui.statusBar->showMessage(tr("listening..."), 1000);
		return;

	}
	else
	{
		if (tcpSocket->ConnectedState) //如果tcp是連上的
		{
			tcpServer->close();
			PushButton_socket_sendforcedata_lisen->setText(tr("監聽"));
			Socket_Text_append(1, "server_disconnect");
			socket_senddatatimer->stop();
			PushButton_socket_sendforcedata->setEnabled(false);
			PushButton_socket_sendforcedata_ontime->setEnabled(false);
			return;
		}
		tcpSocket->disconnectFromHost();
		tcpServer->close();
		PushButton_socket_sendforcedata_lisen->setText(tr("監聽"));
		Socket_Text_append(1, "server_disconnect");
		PushButton_socket_sendforcedata->setEnabled(false);
		PushButton_socket_sendforcedata_ontime->setEnabled(false);
		//qDebug() << "cancel listen sucessful!!";
		ui.statusBar->showMessage(tr("disconnected"), 1000);
	}

}

void zlc_robotplatform::on_PushButton_socket_sendforcedata_ontime_clicked()
{
	if (PushButton_socket_sendforcedata_ontime->text()==tr("定時發送"))
	{
		
		//m_sensorthread->SendDataflag = true;
		//sensortimer->stop();  //只能有一個定時器運行啊!不然送的數據不準!!
		//this->killTimer(id_plot);//只能有一個定時器運行啊!不然送的數據不準!
		socket_senddatatimer->start(10);////只能有一個定時器運行啊!不然送的數據不準!!
		PushButton_socket_sendforcedata_ontime->setText(tr("取消定時"));
		return;

	}
	if (PushButton_socket_sendforcedata_ontime->text() == tr("取消定時"))
	{
		
		
		socket_senddatatimer->stop();
		PushButton_socket_sendforcedata_ontime->setText(tr("定時發送"));
		return;

	}
	
}
void zlc_robotplatform::on_PushButton_socket_sendforcedata_clear_clicked()
{
	Socket_Text_append(1,"",true);
}
void zlc_robotplatform::on_PushButton_socket_sendforcedata_clicked()
{
	QString value;
	value = QString("{Fx=%1,Fy=%2,Fz=%3,Fx=%4,Fy=%5,Fz=%6}").arg(m_sensorthread->pack6D.Fx*0.1)
		.arg(m_sensorthread->pack6D.Fy*0.1).arg(m_sensorthread->pack6D.Fz*0.1).arg(m_sensorthread->pack6D.Tx*0.001)
		.arg(m_sensorthread->pack6D.Ty*0.001).arg(m_sensorthread->pack6D.Tz*0.001);
	QByteArray block = value.toLatin1();
	tcpSocket->write(block);	
	tcpSocket->flush();
	Socket_Text_append(0, value);
}

7 coin3d在qt上的使用
qt上使用coin3D比在MFC上使用簡單的多!!!!關鍵代碼如下:

void zlc_robotplatform::initDock_Coin3d()
{
	SoQt::init(""); //一定要放到最前面
	zlc_tx90 = new TX90_robot;
	QWidget * coin3Dwidget = new QWidget;
	
	ui.dockWidget_coin3d->setWidget(coin3Dwidget);
	zlc_tx90->makeScene();
	myviewer = new SoQtExaminerViewer(coin3Dwidget);
	myviewer->setSceneGraph(zlc_tx90->root);
	myviewer->setBackgroundColor(SbColor(0.35, 0.35, 0.35));
	myviewer->show();
	myviewer->viewAll();
	SoQt::show(coin3Dwidget);
}
zlc_robotplatform::~zlc_robotplatform()
{
	if (myviewer != NULL)
	{
		delete myviewer;
		zlc_tx90->root->unref();
	}
	tcpServer->close();
	tcpServer->deleteLater();

}

8.vs2010+qt5.3.1中文的使用
網上說好像是要安裝vs2010補丁sp1,可以下載試下,我的是卡在office上,不知道安裝成功了沒,然後在頭文件加下面的命令即可使用中文:

// QT版本低於qt5
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
// VS版本低於VS2010
#if defined(_MSC_VER) && (_MSC_VER < 1600)
QTextCodec::setCodecForTr(QTextCodec::codecForName("GBK"));
#else
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
#endif
#else
#if _MSC_VER >= 1600
#pragma execution_character_set("UTF-8")
#endif
#endif
// #if _MSC_VER >= 1600
// #define _MSC_STDINT_H_
// #endif
//上述代碼可解決中文問題

9.一個困擾蠻久常見的錯誤
vs2010+qt4編譯出現error LNK2001: 無法解析的外部符號 "public: virtual struct QMetaObject等錯誤
https://www.cnblogs.com/lovebay/p/9337528.htm
這個錯誤出現在我添加qcustom ,和添加帶Q_Object的類的時候
解決方法如下:右擊帶Q_Object的頭文件,自定義生成工具,添加如下:

命令行:
"$(QTDIR)\bin\moc.exe"  "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp"  -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DSOQT_DLL -DCOIN_DLL -DSOWIN_DLL -DQWT_DLL "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-IC:\Eigen3" "-I$(QTDIR)\include\QWT" "-I$(NOINHERIT)\."
說明:
Moc%27ing zlc_robotplatform.h...
輸出:
.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp
附加依賴項:
$(QTDIR)\bin\moc.exe;%(FullPath)

在這裏插入圖片描述
然後在GeneratedFiles中找到該文件,包含進項目中即可
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章