ros下tcp通信的过程

2023-05-16

                                                       ros框架下的tcp通信的过程

    博主在编写一个需要通过wifi传输两个整数和一个状态的问题中,通过构建ros(Ubuntu16.04)框架下的tcp(c++)通信过程解决了问题。

一、ros串口通信的实现

    首先我们需要从单片机中接收需要传输的数据,为了方便,我将状态和两个整数合成为一个七个字符的字符串传输,在需要调用的地方解析该字符串。

    ros的串口通信我们可以使用官方自带的serial通信包,主要调用了串口打开函数open()和串口读取函数read(),至于ros节点的创建与话题的发布,我在这里不再赘述,不太了解的可以参考http://wiki.ros.org/ROS。

    该ros功能包里我自定义了消息类型wifi_good.msg,虽然里面只有string一种消息类型,但是为以后程序改进留有空间

string message
    具体代码如下:
#include "ros/ros.h"
#include <std_msgs/Empty.h>
#include <std_msgs/String.h>
#include <serial/serial.h>  
#include <std_msgs/String.h>
#include <wifi_nice/wifi_good.h>


serial::Serial ser; 


int main (int argc, char** argv)
{
  //初始化节点
  ros::init(argc, argv, "serial_common_node");
  //声明节点句柄
  ros::NodeHandle nh;
  //发布主题
  ros::Publisher read_pub = nh.advertise<wifi_nice::wifi_good>("read", 33);


  try
  {
  //设置串口属性,并打开串口
      ser.setPort("/dev/ttyUSB0");
      ser.setBaudrate(921600);
      serial::Timeout to = serial::Timeout::simpleTimeout(1000);
      ser.setTimeout(to);
      ser.open();
  }
  catch (serial::IOException& e)
  {
      ROS_ERROR_STREAM("Unable to open port ");
      return -1;
  }
  //检测串口是否已经打开,并给出提示信息
  if(ser.isOpen())
  {
      ROS_INFO_STREAM("Serial Port initialized");
  }
  else
  {
      return -1;
  }


  ros::Rate loop_rate(50);
  while(ros::ok())
  {

      if(ser.available()){
          ROS_INFO_STREAM("Reading from serial port\n");
          wifi_nice::wifi_good result;
          result.message=ser.read(ser.available());
          ROS_INFO_STREAM("Read: " << result.message);
          read_pub.publish(result);
      }

      //处理ROS的信息,比如订阅消息,并调用回调函数
      ros::spinOnce();
      loop_rate.sleep();

  }



}

二、话题的订阅与消息的发送

    以上的代码中将消息发送到滤read话题上,我们通过订阅该话题来实现传输

    为了方便,我在回调函数中写了tcp通信的代码(需要注意的是在每次调用回调函数时,一定要记得在回调函数后面添加ros::spin()或ros::spinOnce()函数,不清楚区别的可以自行百度),通过限定回调函数调用的频率,实现tcp消息传输的循环发送。

博主需要实现一个客户端对应多个服务端,因此定义了多个IP地址,通过定义多个socket来实现该过程。

     tcp传输主要调用了write()函数,具体代码如下:

#include <ros/ros.h>
#include<iostream>
#include<cstring>
#include<string>
#include <fstream>
#include <std_msgs/String.h>
#include <std_msgs/Empty.h>
#include <wifi_nice/wifi_good.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <unistd.h>
#define SERVPORT 8080
#define MAXDATASIZE 100
#define SERVER_IP_1 "192.168.1.102"
#define SERVER_IP_2 "192.168.1.101"
#define SERVER_IP_3 "192.168.1.104"
using namespace std;

void read_callback(const wifi_nice::wifi_good msg)
{
  char DATA[MAXDATASIZE];
  istringstream stream1;
  stream1.str(msg.message);
  int number;
  stream1 >> number;
  sprintf(DATA,"%d",number);
  ROS_INFO_STREAM("RECEIVE: "<< number);


      int sockfd_1;
      struct sockaddr_in serv_addr_1;

	if ((sockfd_1 = socket(AF_INET, SOCK_STREAM, 0)) == -1) {

		perror("socket error!");
		exit(1);
	}

	bzero(&serv_addr_1, sizeof(serv_addr_1));
	serv_addr_1.sin_family = AF_INET;
	serv_addr_1.sin_port = htons(SERVPORT);
	serv_addr_1.sin_addr.s_addr = inet_addr(SERVER_IP_1);

	connect(sockfd_1, (struct sockaddr *) &serv_addr_1, sizeof(struct sockaddr));
        write(sockfd_1, DATA, sizeof(DATA));
	close(sockfd_1);

       
       //int sockfd_2;
       //struct sockaddr_in serv_addr_2;

	//if ((sockfd_2 = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
       
        //	perror("socket error!");
	//	exit(1);
	//}

	//bzero(&serv_addr_2, sizeof(serv_addr_2));
	//serv_addr_2.sin_family = AF_INET;
	//serv_addr_2.sin_port = htons(SERVPORT);
	//serv_addr_2.sin_addr.s_addr = inet_addr(SERVER_IP_2);

	//connect(sockfd_2, (struct sockaddr *) &serv_addr_2, sizeof(struct sockaddr));
	//write(sockfd_2, DATA, sizeof(DATA));
	//close(sockfd_2);

        
        //int sockfd_3;
        //struct sockaddr_in serv_addr_3;

	//if ((sockfd_3 = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        
 		//perror("socket error!");
		//exit(1);
	//}

	//bzero(&serv_addr_3, sizeof(serv_addr_3));
	//serv_addr_3.sin_family = AF_INET;
	//serv_addr_3.sin_port = htons(SERVPORT);
	//serv_addr_3.sin_addr.s_addr = inet_addr(SERVER_IP_3);

	//connect(sockfd_3, (struct sockaddr *) &serv_addr_3, sizeof(struct sockaddr));
	//write(sockfd_3, DATA, sizeof(DATA));
	//close(sockfd_3);

}


int main(int argc, char **argv)
{
  
  ros::init(argc, argv, "listener");
  ros::NodeHandle n;
  ros::Subscriber sub = n.subscribe("read", 1, read_callback);
  ros::spin(); 
  return 0;
}

三、消息的接收与发布

    消息发送后,需要在上位机创建一个功能包实现消息的接受与发布,具体代码如下:

#include <ros/ros.h>
#include <wifi_get/wifi_nice.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <iostream>
#define SERVPORT 8080
#define BACKLOG 10
#define MAXSIZE 1024
using namespace std;

int main(int argc, char **argv)
{

        int sockfd, client_fd;
	struct sockaddr_in my_addr;
	struct sockaddr_in remote_addr;
	//创建套接字
if ((sockfd = socket( AF_INET, SOCK_STREAM, 0 ) )== -1 ){
		perror("socket create failed!");
		exit(1);
	}
	//绑定端口地址
	my_addr.sin_family = AF_INET;
	my_addr.sin_port = htons(SERVPORT);
	my_addr.sin_addr.s_addr = INADDR_ANY;
	bzero(&(my_addr.sin_zero), 8);
	if (bind(sockfd, (struct sockaddr*) &my_addr, sizeof(struct sockaddr))== -1) {
		perror("bind error!");
		exit(1);
	}
	//监听端口
	if (listen(sockfd, BACKLOG) == -1) {
		perror("listen error");
		exit(1);
	}


  //用于解析ROS参数,第三个参数为本节点名
  ros::init(argc, argv, "talker");
  ros::NodeHandle nh;
  wifi_get::wifi_nice msg;
  msg.message="0000000";
  ros::Publisher pub = nh.advertise<wifi_get::wifi_nice>("read", 1);
  ros::Rate loop_rate(1.0);

  while (1)
  {
    
    //int sin_size = sizeof(struct sockaddr_in);
socklen_t sin_size = sizeof(struct sockaddr_in);
if ((client_fd = accept(sockfd,(struct sockaddr*) &remote_addr,&sin_size)) == -1){
			perror("accept error!");
			continue;
		}

                

	
                        char buf[MAXSIZE];
			//接受client发送的请示信息
			int rval;
			
			if ((rval = read(client_fd, buf, MAXSIZE)) < 0) {
				perror("reading stream error!");
				continue;
			}
                

			string s(&buf[0],&buf[strlen(buf)]);  
                        msg.message=s;
                        cout<<"发布的数据为:"<<s<<endl;
                        
			close(client_fd);
	
    
                        pub.publish(msg);
    //根据前面定义的频率, sleep 1s
    loop_rate.sleep();
}
  return 0;
} 

    数据在read话题上发布后,我们在需要应用到传输消息的主函数中通过回调函数,解析传输的消息,实现消息的应用,具体代码如下:

//ROS头文件
#include <ros/ros.h>
#include <string.h>
#include <wifi_get/wifi_nice.h>
#include <unistd.h>
#include <iostream>
using namespace std;


void wifi_Callback(const wifi_get::wifi_nice msg)
{  
    istringstream stream_ck;
    stream_ck.str(msg.message);
    int number;
    stream_ck>>number;
    ROS_INFO_STREAM("msg: "<<msg.message);
    int left,right,get;
    left=number%1000;
    right=(number/1000)%1000;
    get=(number/1000)/1000;
    ROS_INFO_STREAM("left: "<<left<<"     right:"<<right);
    ROS_INFO_STREAM("------------------- ");
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "listener");
  ros::NodeHandle n;
  ros::Subscriber sub = n.subscribe("read", 1, wifi_Callback);
  ros::spin(); 
  return 0;
}
    至此,我们实现了ros框架下tcp通信的问题。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ros下tcp通信的过程 的相关文章

  • 是什么导致 MSSQL 中出现“非阻塞套接字上的操作将阻塞”错误?

    错误 异常查询为 CREATE NONCLUSTERED INDEX I1 ON AllAccounts BAK Master received Day ASC 出现异常 发生一个或多个错误 错误 异常内部异常无法从传输连接读取数据 非阻塞
  • 通过 TCP 客户端套接字接收数据时出现问题

    我正在尝试用 C 语言编写一个 TCP 客户端程序 客户端将在其中启动 连接到服务器 然后它会发送一些信息 然后监听它收到的信息并做出相应的反应 我遇到麻烦的部分是持续聆听 这是我所拥有的 while 1 numbytes recv soc
  • 查找网络中的所有IP地址

    我正在尝试用 C 来做这个 我需要找到我的网络中所有活动的 IP 地址并将它们显示在列表中 我可以 ping 网络中所有可用的 1 255 IP 地址 但我想让这个过程更快 此代码在大约 1 秒内扫描我的网络 255 个 D 级段 我在 V
  • Socket ReceiveAsync 合并数据包

    我打算通过套接字接收数据包 但由于它们是从发送方以高频率发送的 因此其中许多数据包被打包成一个byte array SocketAsyncEventArgs Buffer然后保存多个数据包 即使它们是单独发送的 使用验证wireshark
  • 在 C# 中通过 TCP 发送 C 结构体

    我正在编写一个程序 通过 TCP 与一台设备的管理界面进行交互 问题是 设备的文档是用C写的 而我写的程序是用C 写的 我的问题是 文档指定 通信基于基于C结构的API缓冲区 再多的谷歌搜索似乎也无法让我找到这个 API 或如何通过 TCP
  • Go TCP 读取是非阻塞的

    我正在尝试用 Go 创建服务器和客户端 我已经成功地与服务器和客户端进行通信 但我遇到的问题是golang中的TCP读取是非阻塞的 我想知道 golang 中的读取是否有可能像 C 中的读取一样阻塞 谢谢 EDIT 这是服务器的源代码 fu
  • PHP 上的多个 TCP 套接字请求

    是否可以使用 PHP 上的套接字服务器接受多个请求 并行 如果可以的话 怎样做 普通的 PHP 脚本无法接收多个请求 但如果你真的计划创建一个套接字服务器 作为 cmdline php 脚本启动 那么是的 这是可能的 调查http pear
  • C# - 从客户端检查 TCP/IP 套接字状态

    我想为我的 TCP IP 客户端类提供 CheckConnection 函数 以便我可以检查是否发生了错误 我自己的客户端断开连接 服务器断开连接 服务器卡住等 我有类似的东西 bool isConnectionActive false i
  • 是否可以通过互联网在两个移动设备 (iPhone) 之间连接套接字?

    是否可以通过互联网在两个移动设备 iPhone 之间连接套接字 我正在尝试发现每个设备的IP并直接连接 我知道可以使用 Bonjour 来完成 但这只适用于本地网络 我需要通过互联网在两个设备之间建立高速连接 Thanks 如果你有两个 I
  • 为什么我们可以将 sockaddr 转换为 sockaddr_in

    我明白为什么强制转换很有用sockaddr to sockaddr in 但我不明白这怎么可能 据我所知 它们的大小相同sockaddr in添加了sin zero使其大小相同 我想知道编译器如何知道从哪里获取信息sockaddr in如果
  • 在 Python 中通过 TCP 套接字发送文件

    我已经成功地将文件内容 图像 复制到新文件 然而 当我通过 TCP 套接字尝试同样的事情时 我遇到了问题 服务器循环未退出 客户端循环在到达 EOF 时退出 但服务器无法识别 EOF 这是代码 Server import socket Im
  • 构建多线程 TCP/IP 服务器

    我想构建一个可供最多 100 个并发客户端使用的 TCP IP 服务器 但仍不确定如何开始 至少我需要服务器 监听客户端 并将它们全部存储在数组或列表中 对于每个客户端 它需要根据其客户端状态接收和发送数据 当有人连接或断开连接时 服务器应
  • 在 Golang Server 中接受持久的 tcp 连接

    我正在尝试使用 Go 并且想创建一个 TCP 服务器 我可以通过 telnet 访问该服务器 发送命令并接收响应 const CONN HOST localhost CONN PORT 3333 CONN TYPE tcp func mai
  • 是否可以找到哪个用户位于 localhost TCP 连接的另一端?

    这是一个编程问题 但它是 Linux Unix 特定的 如果我从本地主机获得 TCP 连接 是否有一种简单的方法可以告诉哪个用户在 C 程序内建立了连接而无需 shell 我知道这对于 Unix 域套接字来说并不太难 我已经知道远程 IP
  • 简单的跨平台 TCP IP API?

    我不打算使用像 QT 或 wxWidgets 的 API 这样的大东西 我只想要可以在 Android iOS Windows Mac Linux 上运行的简单套接字 我正在制作一个事件驱动的纸牌游戏 所以 TCP 是最好的 本质上 我只想
  • TcpClient 在异步读取期间断开连接

    我有几个关于完成 tcp 连接的问题 客户端使用 Tcp 连接到我的服务器 在接受客户端后listener BeginAcceptTcpClient ConnectionEstabilishedCallback null 我开始阅读netw
  • 为什么我收到的数据包数据大小大于mss?

    我在两台 PC 上使用 ifconfig ethX mtu 300 修改了 MTU 并使用 netperf 测试网络 我用 WireShark 嗅探了 SYN 数据包中的 MSS 260 但我得到了一些大于 260 的数据包 为什么 嗅探器
  • 当 TCP 序列号到达而不是预期时会发生什么情况?

    我正在编写一个程序 使用 libpcap 捕获数据包并重新组装 TCP 流 我的程序只是监视流量 因此我无法控制数据包的接收和发送 我的程序忽略所有非 TCP IP 流量 我根据 ISN 计算下一个预期序列号 然后计算连续的 SEQ 号 我
  • 为什么tcp终止需要4次握手?

    当连接建立时 有 客户端 SYN gt 服务器 客户端 客户端 ACK gt 服务器 当终止到来时 有 客户端 FIN gt 服务器 客户端 客户端 客户端 ACK gt 服务器 我的问题是为什么 和 不能像 那样设置在同一个包中 即ACK
  • 为什么SOCKS5需要通过UDP中继UDP?

    The SOCKS5 https en wikipedia org wiki SOCKS SOCKS5协议 描述为RFC1928 https www rfc editor org rfc rfc1928提供对 UDP 的支持 总而言之 希望

随机推荐

  • 故障解决:端口已被占用 1080

    更新记录 版本时间修订内容1 02018 3 28增加了方案二1 12019 8 9增加了方案三 问题的提出 实验环境 xff1a Win7 64bit 也许你会碰到以下错误 xff1a 本文给出2种解决方案 方案一 既然说端口已被占用 x
  • git cherry-pick 详解 —— Git 学习笔记 18

    git cherry pick 详解 初识 git cherry pick xff08 拣选 xff09 拣选会提取某次提交的补丁 xff0c 之后尝试将其重新应用到当前分支上 这种方式在你只想引入特性分支中的某个提交时很有用 假设你的项目
  • 问题解决: SSR 的 1080 端口被占用

    问题解决 xff1a SSR 的 1080 端口被占用 在我的博客 故障解决 xff1a 端口已被占用 1080 中已经讨论了一些方法 xff0c 但也不是每次都能成功 对于 SSR xff0c 我们完全可以换一种思路 xff1a 既然 1
  • USB开发简述

    由于工作需要 xff0c 接触了USB xff0c 经过这两三周的学习 xff0c 我只想说一句 xff0c 我们USB说简单也简单 xff0c 说复杂也有那么多知识 xff01 这怎么说呢 xff1f 简单 xff1a 无非就那几个结构体
  • 基于PX4六旋翼无人机百米悬停定点降落

  • 手把手教你实现ROS Melodic+Realsense D435i

    硬件配置 xff1a HP ProDesk 480 G6 MT 系统内存 xff1a 8G 处理器 xff1a Intel i7 8700 CPU 操作系统 xff1a Ubuntu 18 04 相机配置 xff1a Intel Reals
  • pixhawk调试过程中QGC报错显示问题及解决方案汇总

    1 室内环境下解锁无人机 xff0c 报错 xff1a Not arming geofence RTL requiers valid home 解决 xff1a 去掉安全设置里面的地理围栏 xff0c 否则只能在有GPS的环境下解锁
  • pixhawk4连接PX4 Flow光流传感器调试过程记录

    主控型号 Pixhawk4 光流型号 PX4 FLow V1 3 地面站 QGroundControl 1 拔掉PX4 Flow连接Pixhawk4的连接线 用USB连接PX4 Flow 打开QGC地面站 烧写固件 烧写完成后就可以在QGC
  • 使用Xshell连接Ubuntu主机失败

    1 问题 在将一台Ubuntu系统的电脑作为服务器 xff0c 使用Xshell连接时 xff0c 发生如下错误 此时使用ping工具检查是否能够ping通 说明能够连接上 xff0c 但是不能使用Xshell进行远程操作 2 解决方法 首
  • P900数传参数配置

    端口定义 xff1a xff08 从左往右 xff09 GND RX TX 5V 调试软件 xff1a X CTU 启动调试 xff1a 按住数传板上SW2 xff0c 同时按住SW1 xff0c 然后松开SW2 xff0c 再松开SW1
  • 利用ROS实现PX4 offboard板外控制

    基于ROS Melodic xff0c 以px4开发者手册实例程序为例 xff0c 实现gazebo下无人机起飞两米悬停 xff0c 具体操作分为三步 xff1a 1 创建工作空间 xff0c 建立offboard包 2 构建mavros
  • Jetson TX2开发板配置Intel T265环境的必要解决方式

    在Jetson TX2配置T265相关依赖时会发生错误 xff0c 因此需要提前对相关参数进行设置 xff0c 主要要将网络设置里面的相关参数改成下图的配置 xff1a
  • pixhawk日志ulg格式转matlab数据csv格式

    1 windows下打开Anconda Prompt xff0c 执行pip install pyulog安装pyulog包 2 在日志文件所在文件夹下执行ulog2csv 文件名 ulg即可生成相关的csv文件
  • 悲催的秋招之路

    个人情况 双非工科硕 民办本 专科起点 基础不行 专业知识不扎实 无技术无论文无项目 投递记录 企业名称 投递时间 岗位1 岗位2 岗位3 岗位4 国电南自 2021 5 19 嵌入式软件研发工程师 民生银行 2021 5 26 金融科技方
  • Matlab读取EXCEL文本中的数据并绘制二维三维曲线图脚本

    Matlab读取EXCEL文本中的数据并绘制二维三维曲线图需要将EXCEL保存为CSV格式 xff0c 然后取数据成矩阵进行处理 转CSV的方式 xff1a pixhawk日志ulg格式转matlab数据csv格式 1 导入文件 span
  • 零基础教会你用github创建个人博客网站

    1 创建账号 进入github网站 xff0c 在网站首页右上角进行用户注册 2 填写相关信息 按照提示填写相关信息完成用户注册 3 搭建个人博客库 进入个人主页 xff0c 在右上角选择 43 好 xff0c 进入 new reposit
  • SV2-4G移动终端使用配置与使用

    一 硬件连接 1接位置天线 xff0c 2接方向天线 xff0c 3接4G天线 xff0c 4接GPS配置专用线 xff0c 5接4G配置专用线 二 运行状态识别 1处为指示灯 xff08 运行 SIM卡 网络 电源 xff09 xff0c
  • yapi插件开发及安装的一些备注

    yapi官方文档有些缺失 xff0c 这里做一下补充 xff0c 官方文档地址 xff1a https hellosean1025 github io yapi documents redev html 插件开发需要调试 xff0c 这个需
  • VSCode修改编辑器(代码窗口)背景色

    VSCode 的背景色是放在主题里面定义的 xff0c 所以在vscode的设置中无法修改到编辑器也就是代码窗口的背景色 xff0c 对应想要自定义编辑器背景的同志们来说 xff0c 可以通过修改主题文件来实现 xff0c 操作起来也并不复
  • ros下tcp通信的过程

    ros框架下的tcp通信的过程 博主在编写一个需要通过wifi传输两个整数和一个状态的问题中 xff0c 通过构建ros xff08 Ubuntu16 04 框架下的tcp c 43 43 通信过程解决了问题 一 ros串口通信的实现 首先