Windows Sockets network programming and UR robot communication data analysis code

1 Introduction

I wrote several articles about UR robot network control before: " UR robot return information format analysis ", " UR robot communication port and protocol ", many readers asked questions about programming implementation, so upload the relevant code here , for peer reference.

2 contains content

Here I use the VS2015 compilation environment and implement it in C/C++ language.
In fact, there is no advanced technology, it involves two things:

  1. Windows Sockets network programming;
  2. The UR robot returns data content analysis, including the conversion of data bytes.

3 program realization

3.1 Windows Sockets network programming

1) Windows Sockets initialization

At the beginning of the program, perform Windows Sockets initialization. WSAStartup must be the first Windows Sockets function called by an application or DLL. It allows an application or DLL to specify the version number of the Windows Sockets API and to obtain specific Windows Sockets implementation details. An application or DLL can only call further Windows Sockets API functions after a successful WSAStartup() call.

	WSADATA wsaData;
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
	{
		printf("Failed to load Winsock");
		return;
	}

Correspondingly, before the end of the program, call the following statement

	WSACleanup();

2) Establish and disconnect from the server

Establish a Socket communication channel with the server through IP and port. For UR robots, the default IP and port are 192.168.0.77:30003.
First establish a connection:

	char* pIp = "192.168.0.77";
	int nPort = 30003;
	SOCKADDR_IN addrSrv;
	addrSrv.sin_family = AF_INET;
	addrSrv.sin_port = htons(nPort);
	//	addrSrv.sin_addr.S_un.S_addr = inet_addr(pIp);
	inet_pton(AF_INET, pIp, &addrSrv.sin_addr);

	//创建套接字
	m_sockData = socket(AF_INET, SOCK_STREAM, 0);
	if (INVALID_SOCKET == m_sockData) {
		m_nError = WSAGetLastError();
		return;
	}

	//向服务器发出连接请求
	if (connect(m_sockData, (struct  sockaddr*)&addrSrv, sizeof(addrSrv)) == INVALID_SOCKET)
	{
		m_nError = WSAGetLastError();
		CString msg;
		msg.Format(_T("Connect Error=%d"), m_nError);
		AfxMessageBox(msg);
		return;
	}
	//启动接收线程
	m_bThread=true;
	AfxBeginThread(Thread_RecvData, this, THREAD_PRIORITY_IDLE);

Correspondingly, when the last program exits or no longer uses this channel, disconnect:

	if (m_sockData != INVALID_SOCKET)
	{
		shutdown(m_sockData, 0);
		closesocket(m_sockData);
		m_sockData = INVALID_SOCKET;
	}

3) Data reception

Network Sockets data is transmitted asynchronously, and the receiving function recv() used is blocking, that is, the function does not return until no receiving event occurs (data is received normally, error occurs, receiving timeout, ...) , so I put the data receiving in a dedicated receiving thread.

UINT CURCommDlg::Thread_RecvData(PVOID pParam)
{
	CURCommDlg* pDlg = (CURCommDlg*)pParam;
	int nLen = 1024;
	char* recvBuf = new char[nLen];
	memset(recvBuf, 0, nLen);
	while (pDlg->m_bThread)
	{
		//	//接收数据
		int ret = recv(pDlg->m_sockData, recvBuf, nLen, 0);
		if (ret>0)
		{
			pDlg->OnRecvData(recvBuf, ret);
		}
		else
		{
			//recv error
			pDlg->m_nError = WSAGetLastError();
			closesocket(pDlg->m_sockData);
			break;
		}
	}
	delete[]recvBuf;
	pDlg->m_bThread = false;
	return 1;
}

3.2 Data content analysis

The data received by the above network is sent to the OnRecvData function for data analysis.
Here, it is analyzed according to the data format returned by port 30003 of the UR robot. For the specific data format, see " Analysis of the Returned Information Format of the UR Robot ".

void CURCommDlg::OnRecvData(char* pData, int nLen)
{
	DWORD dwPackLen;
	dwPackLen = GetDword((PBYTE)pData);
	double data1[54];
	int n;
	for (n = 0; n < 54; n++)
	{
		data1[n] = GetDouble((PBYTE)(pData + 12 + n * 8));
	}
	double data2[30];
	for (n = 0; n < 30; n++)
	{
		data2[n] = GetDouble((PBYTE)(pData + 444 + n * 8));
	}
	for (n = 0; n < 6; n++)
		m_dCurPos[n] = data2[n];
}

Among them, since the data returned by UR is Big-Endian, and the data in the computer is Little-Endian, the data byte conversion must be performed, so the following two functions are compiled to complete it. In fact, the following GetDword function has the same function as the htonl() function .

double GetDouble(PBYTE pData)
{
	double t;
	PBYTE p = (PBYTE)&t;
	int i;
	for (i = 0; i < 8; i++)
	{
		p[i] = pData[7 - i];
	}
	return t;
}

DWORD GetDword(PBYTE pData)
{
	DWORD t;
	PBYTE p = (PBYTE)&t;
	int i;
	for (i = 0; i < 4; i++)
	{
		p[i] = pData[3 - i];
	}
	return t;
}

The parsed data can be used for other purposes of the program. For example, m_dCurPos[6] in the above parsing function is the six data of the robot's current real-time pose.
The complete project of the above code can be viewed on the download page

Guess you like

Origin blog.csdn.net/hangl_ciom/article/details/104439042