Ubuntu18.04 ROS udp Client通信实现
此小节介绍udp Client收发数据。udp通信属于帧传输,在帧传输过程中对于消息的次序和到达情况没有需求,没有进行校验,所以UDP属于不可靠传输,但是由于缺少的校验时间,udp通信在一些环境下(比如无线传输,网络信号较差时)通信效率较高,此通信方式通常用于实时性要求较高的传感器信息回传(比如视频流,语音流的回传)。 下一节介绍介绍Ubuntu18.04 ROS与Android tcp/ip的通信实现,后续Ubuntu介绍串口通信的灵活运用,通过Android与工控机串口的配合实现车辆遥控操作。 本小节测试工具,Windows使用USR-TCP232-Test-V1.3 udp或者TCP&UDP测试工具,Ubuntu18.04/ROS udp/client进行连接。 关于Ubuntu ros下tcp/ip udp/Server服务器客户端的简单实现可以参考1.1 ; 1.2;1.3
测试过程和效果
我的测试平台为Ubuntu18.04 与Windows系统上的USR-TCP232-Test-V1.3 测试工具进行通信测试。 以下的1,2步骤前三节介绍类似. 1.保证两台电脑在同一个网络下,并查看Ubuntu的本机IP,在设置->wifi->中可查看,如下图,192.168.2.204,为本机IP。
- 相互ping另外一台电脑的ip,通则说明两台电脑在同一网络下连接成功。windows打开网络串口助手可自动获取本机IP,也可以在网络状态->详细信息中查看IP。如下图,如果ping失败请查看防护墙是否关闭。
3 ping成功之后,进行通信效果测试,首先启动USR-TCP232-Test-V1.3测试工具,然后Ubuntu运行roscore,再然后启动服务器节点,运行效果如下: Windows: Ubuntu:
ROS工作区间和功能包的创建
ROS工作区间和功能包的创建网上资料比较多,这里简单说明。其中使用RoboWare Studio,这个过程变的更简单。
mkdir catkin_ws
cd catkin_ws
mkdir src
cd src
catkin_init_workspace
cd ..
catkin_make
source ~/catkin_ws/devel/setup.bash
cd ~/catkin_ws/src
catkin_create_pkg ros_socket std_msgs rospy roscpp
touch udp_client.cpp
add_executable(udp_client
src/udp_client.cpp
)
add_dependencies(udp_client ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(udp_client
${catkin_LIBRARIES}
)
ROS UDP Client的实现代码
本代码里没有进行话题的订阅和发布,大家可以自行添加测试,代码注释比较清楚。 代码主要包括以下步骤: 1 .创建ros句柄 2.创建一个socket 3.输入服务器IP和端口 4.打包要发送的数据和进行校验,也可以在话题回调函数中进行数据打包。 5.接收数据并显示 程序注释的比较清楚,可以看看。
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <ros/ros.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define DEST_PORT 1024
#define DSET_IP_ADDRESS "192.168.2.130"
int main(int argc, char** argv)
{
ros::init(argc, argv, "udp_port");
ros::NodeHandle n;
int sock_fd;
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
if(sock_fd < 0)
{
perror("socket");
exit(1);
}
struct sockaddr_in addr_serv;
int len;
memset(&addr_serv, 0, sizeof(addr_serv));
addr_serv.sin_family = AF_INET;
addr_serv.sin_addr.s_addr = inet_addr(DSET_IP_ADDRESS);
addr_serv.sin_port = htons(DEST_PORT);
len = sizeof(addr_serv);
int send_num;
int recv_num;
char send_buf[100]={0};
for (int i = 0; i < 71; i++)
{
send_buf[i] = i;
}
uint8_t mycheck;
int i=0;
char recv_buf[100];
ros::Rate loop_rate(50);
while(ros::ok())
{
for(i=0;i<71;i++)
{
mycheck ^= send_buf[i];
}
send_buf[71]= mycheck;
send_buf[72]=0xEE;
send_buf[73]=0xDD;
send_num = sendto(sock_fd, send_buf, 74, 0, (struct sockaddr *)&addr_serv, len);
if(send_num < 0)
{
perror("sendto error:");
exit(1);
}
recv_num = recvfrom(sock_fd, recv_buf, sizeof(recv_buf), 0, (struct sockaddr *)&addr_serv, (socklen_t *)&len);
if(recv_num < 0)
{
perror("recvfrom error:");
exit(1);
}
recv_buf[recv_num] = '\0';
printf("client receive %d bytes: %s\n", recv_num, recv_buf);
ros::spinOnce();
loop_rate.sleep();
}
close(sock_fd);
return 0;
}
功能包程序。 欢迎大家批评指正!!!
|