记一次和iiwa相关的项目,需要用到C++与matlab进行数据的实时通讯。数据的传输暂时只需要机器人的关节角度及空间坐标姿态(长度为7的double型数组)
由于大部分的功能实现在matlab端,c++端作为调用,故将Server端实现在Matlab,Client端实现在C++。
代码如下:
客户端(C++)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#define MAXLINE 4096
#define IP "127.0.0.1"
double joint[6]={10.123456,11.123456,12.123456,13.123456,14.123456,15.123456};
double joint1[7]={0};
const int len_double = sizeof(double);
void *dtoc(void *s,char *m,size_t n)//double型转换成char型
{
char *ss = s;
for (int i = 0; i < n; i++)
m[i]=ss[i];
return m;
}
void btos(char *s)//小端模式:低字节在低位,高字节在高地址
{
char send_arr[len_double];
for(int j=0;j<7;j++){
for(int i=0;i<len_double;i++){
send_arr[i]=s[i+j*len_double];
}
for(int i=0;i<len_double;i++){
s[7-i+j*len_double]=send_arr[i];
}
}
}
void *ctod(void *s,double *m,size_t n)//char型转换成double型
{
double *ss = s;
for (int i = 0; i < 7; i++)
m[i]=ss[i];
return m;
}
int main(){
int sockfd, n;
char recvline[4096], sendline[4096];
struct sockaddr_in servaddr;
//建立一个socket
if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
printf("create socket error: %s(errno: %d)\n", strerror(errno),errno);
return 0;
}
//初始化 将串口号等信息进行绑定
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
servaddr.sin_port = htons(6668);
//主动连接服务器
if( connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0){
printf("connect error: %s(errno: %d)\n",strerror(errno),errno);
return 0;
}
printf("连接成功\n");
int num=0;
// while(1){
printf("send msg to server: \n");
dtoc(joint,sendline,sizeof(joint));
btos(sendline);
//printf("%s\n",sendline);
send(sockfd, sendline, strlen(sendline), 0);
//strlen:用字符数组数量的末地址减去首地址计算字符长度
// if( send(sockfd, sendline, strlen(sendline), 0) < 0){
// printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);
// return 0;
// }
recv(sockfd, recvline, MAXLINE, 0);
btos(recvline);
ctod(recvline,joint1,sizeof(recvline));
printf("%d\n",num++);
for(int i=0;i<7;i++){
printf(" %f ", joint1[i]);
};
printf("\n");
// }
close(sockfd);
return 0;
}对上述代码进行解释:该代码主要分为两个部分。1、与来自Matlab的服务端进行通讯。2、将目标数组转换成方便传输读取的形式。
1、与来自Matlab的服务端进行通讯。采用传统的TCP(socket通讯)
服务器端先初始化socket,然后与端口绑定,对端口进行监听,调用accept阻塞,等待客户端连接。
socket() -> bind() -> listen() -> accept()
客户端先初始化socket,然后与服务端连接,服务端监听成功则连接建立完成
socket() -> connect()
2、将目标数组转换成方便传输读取的形式。
传输数据的格式选为char型(c++传输据说只能用char型,待有时间了验证一下,理论上应该都行才对),小端模式(低字节在低位,高字节在高位)
转换的部分有两点:1、将双精度数组转成char型,将char型转为双精度型;2、将数据格式转换为小端格式。分别为dtoc和ctod函数,及btos函数。
服务端(Matlab)
t_server=tcpip('127.0.0.1',6668,'NetworkRole','server');%与第一个请求连接的客户机建立连接,端口号为6668,类型为服务器。
t_server.InputBuffersize=10000;%缓冲区放大到10000
fopen(t_server);%打开服务器,直到建立一个TCP连接才返回;
sprintf("成功建立连接");
pause(1);
while(1)
while(1)%等到缓存区有数据就跳出循环
if t_server.BytesAvailable>0
%t_server.BytesAvailable%显示缓存区字节数
break;
end
end
data_recv=(fread(t_server,t_server.BytesAvailable));%从缓冲区读取数字数据
%%%
data_send=[40.123456,21.123456,22.123456,23.123456,24.123456,25.123456,1];
send1=num2hex(data_send);%转成16进制
send2=[];
for j = 1:length(data_send)
send2 = [send2,send1(j,:)]; %小端模式
end
count1 = 0;
send3 = []; %转化成double
while count1 < length(data_send)*8
send3 = [send3,hex2dec(send2((count1*2+1):(count1*2+2)))];
count1 = count1 + 1;
end
fwrite(t_server,send3,'char');
end
fclose(t_server);%%%%将传入的char数组转成double型%%%%
recv1 = dec2hex(data_recv);%ACSII码转换成16进制
recv2 = []; %将数据按小端形式放在一起
for i = 1:length(recv1)
recv2 = [recv2,recv1(i,:)]; %小端模式
end
%转化成double
count = 0;
recv3 = [];
while count < length(recv1)/8
recv3 = [recv3,hex2num(recv2((count*16+1):(count*16+16)))];
count = count + 1;
end
%%%将double型转成char数组%%%%%%
send1=num2hex(data_send);%转成16进制
send2=[];
for j = 1:length(data_send)
send2 = [send2,send1(j,:)]; %小端模式
end
%转化成double
count1 = 0;
send3 = [];
while count1 < length(data_send)*8
send3 = [send3,hex2dec(send2((count1*2+1):(count1*2+2)))];
count1 = count1 + 1;
end
Matlab部分除去TCP连接外,主要是关于将C++传入的char数组转换为double型,及将double型转换成char型再传给C++,转换原理为将10进制数转为16进制后,以小端模式放在一起,然后按所需的数据类型进行分割,在转回10进制数。
本文参考:Visual Studio C++与 Matlab 进行 TCP/IP 通信传送 double 类型数据
新人文章,如有错漏,欢迎大佬指出。